@enactprotocol/shared 1.0.12
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/dist/LocalToolResolver.d.ts +84 -0
- package/dist/LocalToolResolver.js +353 -0
- package/dist/api/enact-api.d.ts +124 -0
- package/dist/api/enact-api.js +406 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/types.d.ts +83 -0
- package/dist/api/types.js +1 -0
- package/dist/core/DaggerExecutionProvider.d.ts +169 -0
- package/dist/core/DaggerExecutionProvider.js +996 -0
- package/dist/core/DirectExecutionProvider.d.ts +23 -0
- package/dist/core/DirectExecutionProvider.js +406 -0
- package/dist/core/EnactCore.d.ts +138 -0
- package/dist/core/EnactCore.js +609 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/dist/exec/index.d.ts +3 -0
- package/dist/exec/index.js +3 -0
- package/dist/exec/logger.d.ts +11 -0
- package/dist/exec/logger.js +57 -0
- package/dist/exec/validate.d.ts +5 -0
- package/dist/exec/validate.js +167 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +29 -0
- package/dist/lib/enact-direct.d.ts +156 -0
- package/dist/lib/enact-direct.js +158 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/dist/security/index.d.ts +3 -0
- package/dist/security/index.js +3 -0
- package/dist/security/security.d.ts +23 -0
- package/dist/security/security.js +137 -0
- package/dist/security/sign.d.ts +103 -0
- package/dist/security/sign.js +532 -0
- package/dist/security/verification-enforcer.d.ts +41 -0
- package/dist/security/verification-enforcer.js +181 -0
- package/dist/services/McpCoreService.d.ts +102 -0
- package/dist/services/McpCoreService.js +120 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.js +3 -0
- package/dist/utils/config.d.ts +32 -0
- package/dist/utils/config.js +78 -0
- package/dist/utils/env-loader.d.ts +54 -0
- package/dist/utils/env-loader.js +270 -0
- package/dist/utils/help.d.ts +36 -0
- package/dist/utils/help.js +248 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/logger.d.ts +35 -0
- package/dist/utils/logger.js +75 -0
- package/dist/utils/silent-monitor.d.ts +67 -0
- package/dist/utils/silent-monitor.js +242 -0
- package/dist/utils/timeout.d.ts +5 -0
- package/dist/utils/timeout.js +23 -0
- package/dist/utils/version.d.ts +4 -0
- package/dist/utils/version.js +14 -0
- package/dist/web/env-manager-server.d.ts +29 -0
- package/dist/web/env-manager-server.js +367 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js +1 -0
- package/package.json +79 -0
- package/src/LocalToolResolver.ts +424 -0
- package/src/api/enact-api.ts +569 -0
- package/src/api/index.ts +2 -0
- package/src/api/types.ts +93 -0
- package/src/core/DaggerExecutionProvider.ts +1308 -0
- package/src/core/DirectExecutionProvider.ts +484 -0
- package/src/core/EnactCore.ts +833 -0
- package/src/core/index.ts +3 -0
- package/src/exec/index.ts +3 -0
- package/src/exec/logger.ts +63 -0
- package/src/exec/validate.ts +238 -0
- package/src/index.ts +42 -0
- package/src/lib/enact-direct.ts +258 -0
- package/src/lib/index.ts +1 -0
- package/src/security/index.ts +3 -0
- package/src/security/security.ts +188 -0
- package/src/security/sign.ts +797 -0
- package/src/security/verification-enforcer.ts +268 -0
- package/src/services/McpCoreService.ts +203 -0
- package/src/services/index.ts +1 -0
- package/src/types.ts +190 -0
- package/src/utils/config.ts +97 -0
- package/src/utils/env-loader.ts +370 -0
- package/src/utils/help.ts +257 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/logger.ts +83 -0
- package/src/utils/silent-monitor.ts +328 -0
- package/src/utils/timeout.ts +26 -0
- package/src/utils/version.ts +16 -0
- package/src/web/env-manager-server.ts +465 -0
- package/src/web/index.ts +1 -0
- package/src/web/static/app.js +663 -0
- package/src/web/static/index.html +117 -0
- package/src/web/static/style.css +291 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// src/security/verification-enforcer.ts - Mandatory signature verification enforcement
|
|
2
|
+
import {
|
|
3
|
+
verifyTool,
|
|
4
|
+
VERIFICATION_POLICIES,
|
|
5
|
+
type VerificationPolicy,
|
|
6
|
+
} from "./sign";
|
|
7
|
+
import type { EnactTool, ExecutionResult } from "../types";
|
|
8
|
+
import logger from "../exec/logger";
|
|
9
|
+
|
|
10
|
+
export interface VerificationEnforcementOptions {
|
|
11
|
+
skipVerification?: boolean;
|
|
12
|
+
verifyPolicy?: "permissive" | "enterprise" | "paranoid";
|
|
13
|
+
force?: boolean;
|
|
14
|
+
allowUnsigned?: boolean; // Explicit flag for allowing unsigned tools (only for dev/testing)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface VerificationEnforcementResult {
|
|
18
|
+
allowed: boolean;
|
|
19
|
+
reason: string;
|
|
20
|
+
verificationResult?: {
|
|
21
|
+
isValid: boolean;
|
|
22
|
+
message: string;
|
|
23
|
+
validSignatures: number;
|
|
24
|
+
totalSignatures: number;
|
|
25
|
+
verifiedSigners: Array<{ signer: string; role?: string; keyId: string }>;
|
|
26
|
+
errors: string[];
|
|
27
|
+
};
|
|
28
|
+
error?: {
|
|
29
|
+
message: string;
|
|
30
|
+
code: string;
|
|
31
|
+
details?: any;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Enforce mandatory signature verification for tool execution
|
|
37
|
+
* This is the central function that should be called before ANY tool execution
|
|
38
|
+
*/
|
|
39
|
+
export async function enforceSignatureVerification(
|
|
40
|
+
tool: EnactTool,
|
|
41
|
+
options: VerificationEnforcementOptions = {},
|
|
42
|
+
): Promise<VerificationEnforcementResult> {
|
|
43
|
+
const toolName = tool.name || "unknown";
|
|
44
|
+
|
|
45
|
+
// Check if verification is explicitly skipped
|
|
46
|
+
if (options.skipVerification) {
|
|
47
|
+
logger.warn(
|
|
48
|
+
`🚨 SECURITY WARNING: Signature verification skipped for tool: ${toolName}`,
|
|
49
|
+
);
|
|
50
|
+
logger.warn(
|
|
51
|
+
` This bypasses security measures and is NOT recommended for production use!`,
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
allowed: true,
|
|
56
|
+
reason: `Verification skipped by request for tool: ${toolName}`,
|
|
57
|
+
verificationResult: {
|
|
58
|
+
isValid: false,
|
|
59
|
+
message: "Verification skipped",
|
|
60
|
+
validSignatures: 0,
|
|
61
|
+
totalSignatures: 0,
|
|
62
|
+
verifiedSigners: [],
|
|
63
|
+
errors: ["Signature verification was explicitly skipped"],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Check if tool has any signatures
|
|
69
|
+
const hasSignatures =
|
|
70
|
+
!!(tool.signatures && Object.keys(tool.signatures).length > 0) ||
|
|
71
|
+
!!tool.signature;
|
|
72
|
+
|
|
73
|
+
if (!hasSignatures) {
|
|
74
|
+
logger.warn(`⚠️ Tool has no signatures: ${toolName}`);
|
|
75
|
+
|
|
76
|
+
// Only allow unsigned tools if explicitly permitted (for development/testing)
|
|
77
|
+
if (options.allowUnsigned) {
|
|
78
|
+
logger.warn(
|
|
79
|
+
` Allowing unsigned tool execution due to allowUnsigned flag (DEV/TEST ONLY)`,
|
|
80
|
+
);
|
|
81
|
+
return {
|
|
82
|
+
allowed: true,
|
|
83
|
+
reason: `Unsigned tool allowed by explicit permission: ${toolName}`,
|
|
84
|
+
verificationResult: {
|
|
85
|
+
isValid: false,
|
|
86
|
+
message: "No signatures found, but execution allowed",
|
|
87
|
+
validSignatures: 0,
|
|
88
|
+
totalSignatures: 0,
|
|
89
|
+
verifiedSigners: [],
|
|
90
|
+
errors: [
|
|
91
|
+
"Tool has no signatures but execution was explicitly allowed",
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Reject unsigned tools by default
|
|
98
|
+
return {
|
|
99
|
+
allowed: false,
|
|
100
|
+
reason: `Tool has no signatures and unsigned execution is not permitted: ${toolName}`,
|
|
101
|
+
error: {
|
|
102
|
+
message: `Tool "${toolName}" has no cryptographic signatures. For security, only signed tools can be executed.`,
|
|
103
|
+
code: "NO_SIGNATURES_FOUND",
|
|
104
|
+
details: {
|
|
105
|
+
toolName,
|
|
106
|
+
hasSignature: !!tool.signature,
|
|
107
|
+
hasSignatures: !!tool.signatures,
|
|
108
|
+
signatureCount: tool.signatures
|
|
109
|
+
? Object.keys(tool.signatures).length
|
|
110
|
+
: 0,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Perform signature verification
|
|
117
|
+
try {
|
|
118
|
+
logger.info(`🔐 Verifying signatures for tool: ${toolName}`);
|
|
119
|
+
|
|
120
|
+
// Determine verification policy
|
|
121
|
+
const policyKey = (options.verifyPolicy || "permissive").toUpperCase() as
|
|
122
|
+
| "PERMISSIVE"
|
|
123
|
+
| "ENTERPRISE"
|
|
124
|
+
| "PARANOID";
|
|
125
|
+
const policy: VerificationPolicy =
|
|
126
|
+
VERIFICATION_POLICIES[policyKey] || VERIFICATION_POLICIES.PERMISSIVE;
|
|
127
|
+
|
|
128
|
+
logger.info(` Using verification policy: ${policyKey.toLowerCase()}`);
|
|
129
|
+
if (policy.minimumSignatures) {
|
|
130
|
+
logger.info(
|
|
131
|
+
` Minimum signatures required: ${policy.minimumSignatures}`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (policy.requireRoles) {
|
|
135
|
+
logger.info(` Required roles: ${policy.requireRoles.join(", ")}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Verify the tool
|
|
139
|
+
const verificationResult = await verifyTool(tool, policy);
|
|
140
|
+
|
|
141
|
+
if (verificationResult.isValid) {
|
|
142
|
+
logger.info(`✅ Signature verification passed for tool: ${toolName}`);
|
|
143
|
+
logger.info(
|
|
144
|
+
` Valid signatures: ${verificationResult.validSignatures}/${verificationResult.totalSignatures}`,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
if (verificationResult.verifiedSigners.length > 0) {
|
|
148
|
+
logger.info(
|
|
149
|
+
` Verified signers: ${verificationResult.verifiedSigners
|
|
150
|
+
.map((s) => `${s.signer}${s.role ? ` (${s.role})` : ""}`)
|
|
151
|
+
.join(", ")}`,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
allowed: true,
|
|
157
|
+
reason: `Tool signature verification passed: ${verificationResult.message}`,
|
|
158
|
+
verificationResult,
|
|
159
|
+
};
|
|
160
|
+
} else {
|
|
161
|
+
logger.error(`❌ Signature verification failed for tool: ${toolName}`);
|
|
162
|
+
logger.error(` Policy: ${policyKey.toLowerCase()}`);
|
|
163
|
+
logger.error(
|
|
164
|
+
` Valid signatures: ${verificationResult.validSignatures}/${verificationResult.totalSignatures}`,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
if (verificationResult.errors.length > 0) {
|
|
168
|
+
logger.error(` Errors:`);
|
|
169
|
+
verificationResult.errors.forEach((error) =>
|
|
170
|
+
logger.error(` - ${error}`),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
allowed: false,
|
|
176
|
+
reason: `Tool signature verification failed: ${verificationResult.message}`,
|
|
177
|
+
verificationResult,
|
|
178
|
+
error: {
|
|
179
|
+
message: `Tool "${toolName}" failed signature verification. ${verificationResult.message}`,
|
|
180
|
+
code: "SIGNATURE_VERIFICATION_FAILED",
|
|
181
|
+
details: {
|
|
182
|
+
toolName,
|
|
183
|
+
policy: policyKey.toLowerCase(),
|
|
184
|
+
validSignatures: verificationResult.validSignatures,
|
|
185
|
+
totalSignatures: verificationResult.totalSignatures,
|
|
186
|
+
errors: verificationResult.errors,
|
|
187
|
+
verifiedSigners: verificationResult.verifiedSigners,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
} catch (error) {
|
|
193
|
+
const errorMessage =
|
|
194
|
+
error instanceof Error ? error.message : "Unknown verification error";
|
|
195
|
+
logger.error(
|
|
196
|
+
`💥 Signature verification error for tool: ${toolName} - ${errorMessage}`,
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
allowed: false,
|
|
201
|
+
reason: `Signature verification error: ${errorMessage}`,
|
|
202
|
+
error: {
|
|
203
|
+
message: `Signature verification failed due to error: ${errorMessage}`,
|
|
204
|
+
code: "VERIFICATION_ERROR",
|
|
205
|
+
details: { toolName, originalError: error },
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Create an execution result for verification failure
|
|
213
|
+
*/
|
|
214
|
+
export function createVerificationFailureResult(
|
|
215
|
+
tool: EnactTool,
|
|
216
|
+
verificationResult: VerificationEnforcementResult,
|
|
217
|
+
executionId: string,
|
|
218
|
+
): ExecutionResult {
|
|
219
|
+
return {
|
|
220
|
+
success: false,
|
|
221
|
+
error: verificationResult.error || {
|
|
222
|
+
message: verificationResult.reason,
|
|
223
|
+
code: "VERIFICATION_FAILED",
|
|
224
|
+
},
|
|
225
|
+
metadata: {
|
|
226
|
+
executionId,
|
|
227
|
+
toolName: tool.name || "unknown",
|
|
228
|
+
version: tool.version,
|
|
229
|
+
executedAt: new Date().toISOString(),
|
|
230
|
+
environment: "direct",
|
|
231
|
+
command: tool.command,
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Log security audit information for tool execution
|
|
238
|
+
*/
|
|
239
|
+
export function logSecurityAudit(
|
|
240
|
+
tool: EnactTool,
|
|
241
|
+
verificationResult: VerificationEnforcementResult,
|
|
242
|
+
executionAllowed: boolean,
|
|
243
|
+
options: VerificationEnforcementOptions,
|
|
244
|
+
) {
|
|
245
|
+
const auditLog = {
|
|
246
|
+
timestamp: new Date().toISOString(),
|
|
247
|
+
tool: tool.name || "unknown",
|
|
248
|
+
version: tool.version,
|
|
249
|
+
command: tool.command,
|
|
250
|
+
executionAllowed,
|
|
251
|
+
verificationSkipped: options.skipVerification || false,
|
|
252
|
+
verificationPolicy: options.verifyPolicy || "permissive",
|
|
253
|
+
verificationResult: verificationResult.verificationResult
|
|
254
|
+
? {
|
|
255
|
+
isValid: verificationResult.verificationResult.isValid,
|
|
256
|
+
validSignatures:
|
|
257
|
+
verificationResult.verificationResult.validSignatures,
|
|
258
|
+
totalSignatures:
|
|
259
|
+
verificationResult.verificationResult.totalSignatures,
|
|
260
|
+
verifiedSigners:
|
|
261
|
+
verificationResult.verificationResult.verifiedSigners,
|
|
262
|
+
}
|
|
263
|
+
: null,
|
|
264
|
+
errors: verificationResult.error ? [verificationResult.error.message] : [],
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
logger.info(`🔍 Security Audit Log:`, auditLog);
|
|
268
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// src/services/McpCoreService.ts - Direct core integration for MCP server
|
|
2
|
+
import { EnactCore } from "../core/EnactCore";
|
|
3
|
+
import type { EnactTool, ExecutionResult } from "../types";
|
|
4
|
+
import type { ToolSearchOptions, ToolExecuteOptions } from "../core/EnactCore";
|
|
5
|
+
|
|
6
|
+
export class McpCoreService {
|
|
7
|
+
private core: EnactCore;
|
|
8
|
+
|
|
9
|
+
constructor(options?: {
|
|
10
|
+
apiUrl?: string;
|
|
11
|
+
supabaseUrl?: string;
|
|
12
|
+
authToken?: string;
|
|
13
|
+
}) {
|
|
14
|
+
this.core = new EnactCore({
|
|
15
|
+
apiUrl: options?.apiUrl || "https://enact.tools",
|
|
16
|
+
supabaseUrl:
|
|
17
|
+
options?.supabaseUrl || "https://xjnhhxwxovjifdxdwzih.supabase.co",
|
|
18
|
+
authToken: options?.authToken,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Set authentication token
|
|
24
|
+
*/
|
|
25
|
+
setAuthToken(token: string): void {
|
|
26
|
+
this.core.setAuthToken(token);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Search for tools
|
|
31
|
+
*/
|
|
32
|
+
async searchTools(
|
|
33
|
+
query: string,
|
|
34
|
+
options?: {
|
|
35
|
+
limit?: number;
|
|
36
|
+
tags?: string[];
|
|
37
|
+
author?: string;
|
|
38
|
+
},
|
|
39
|
+
): Promise<EnactTool[]> {
|
|
40
|
+
const searchOptions: ToolSearchOptions = {
|
|
41
|
+
query,
|
|
42
|
+
limit: options?.limit,
|
|
43
|
+
tags: options?.tags,
|
|
44
|
+
author: options?.author,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return await this.core.searchTools(searchOptions);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get a specific tool by name
|
|
52
|
+
*/
|
|
53
|
+
async getToolInfo(name: string): Promise<EnactTool | null> {
|
|
54
|
+
return await this.core.getToolByName(name);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Execute a tool by name
|
|
59
|
+
*/
|
|
60
|
+
async executeToolByName(
|
|
61
|
+
name: string,
|
|
62
|
+
inputs: Record<string, any> = {},
|
|
63
|
+
options?: {
|
|
64
|
+
timeout?: string;
|
|
65
|
+
verifyPolicy?: "permissive" | "enterprise" | "paranoid";
|
|
66
|
+
skipVerification?: boolean;
|
|
67
|
+
force?: boolean;
|
|
68
|
+
dryRun?: boolean;
|
|
69
|
+
},
|
|
70
|
+
): Promise<ExecutionResult> {
|
|
71
|
+
const executeOptions: ToolExecuteOptions = {
|
|
72
|
+
timeout: options?.timeout,
|
|
73
|
+
verifyPolicy: options?.verifyPolicy,
|
|
74
|
+
skipVerification: options?.skipVerification,
|
|
75
|
+
force: options?.force,
|
|
76
|
+
dryRun: options?.dryRun,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return await this.core.executeToolByName(name, inputs, executeOptions);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Execute a tool from raw YAML definition
|
|
84
|
+
*/
|
|
85
|
+
async executeRawTool(
|
|
86
|
+
toolYaml: string,
|
|
87
|
+
inputs: Record<string, any> = {},
|
|
88
|
+
options?: {
|
|
89
|
+
timeout?: string;
|
|
90
|
+
skipVerification?: boolean;
|
|
91
|
+
force?: boolean;
|
|
92
|
+
dryRun?: boolean;
|
|
93
|
+
},
|
|
94
|
+
): Promise<ExecutionResult> {
|
|
95
|
+
const executeOptions: ToolExecuteOptions = {
|
|
96
|
+
timeout: options?.timeout,
|
|
97
|
+
skipVerification: options?.skipVerification,
|
|
98
|
+
force: options?.force,
|
|
99
|
+
dryRun: options?.dryRun,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return await this.core.executeRawTool(toolYaml, inputs, executeOptions);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Verify a tool's signature
|
|
107
|
+
*/
|
|
108
|
+
async verifyTool(
|
|
109
|
+
name: string,
|
|
110
|
+
policy?: string,
|
|
111
|
+
): Promise<{
|
|
112
|
+
verified: boolean;
|
|
113
|
+
signatures: any[];
|
|
114
|
+
policy: string;
|
|
115
|
+
errors?: string[];
|
|
116
|
+
}> {
|
|
117
|
+
return await this.core.verifyTool(name, policy);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Check if a tool exists
|
|
122
|
+
*/
|
|
123
|
+
async toolExists(name: string): Promise<boolean> {
|
|
124
|
+
return await this.core.toolExists(name);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get tools by tags
|
|
129
|
+
*/
|
|
130
|
+
async getToolsByTags(
|
|
131
|
+
tags: string[],
|
|
132
|
+
limit: number = 20,
|
|
133
|
+
): Promise<EnactTool[]> {
|
|
134
|
+
return await this.core.getToolsByTags(tags, limit);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get tools by author
|
|
139
|
+
*/
|
|
140
|
+
async getToolsByAuthor(
|
|
141
|
+
author: string,
|
|
142
|
+
limit: number = 20,
|
|
143
|
+
): Promise<EnactTool[]> {
|
|
144
|
+
return await this.core.getToolsByAuthor(author, limit);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get all tools with filters
|
|
149
|
+
*/
|
|
150
|
+
async getTools(options?: {
|
|
151
|
+
limit?: number;
|
|
152
|
+
offset?: number;
|
|
153
|
+
tags?: string[];
|
|
154
|
+
author?: string;
|
|
155
|
+
}): Promise<EnactTool[]> {
|
|
156
|
+
return await this.core.getTools(options);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get authentication status
|
|
161
|
+
*/
|
|
162
|
+
async getAuthStatus(): Promise<{
|
|
163
|
+
authenticated: boolean;
|
|
164
|
+
user?: string;
|
|
165
|
+
server?: string;
|
|
166
|
+
}> {
|
|
167
|
+
return await this.core.getAuthStatus();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Check if service is available (always true for core service)
|
|
172
|
+
*/
|
|
173
|
+
async isAvailable(): Promise<boolean> {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Get service path info (not applicable for core service)
|
|
179
|
+
*/
|
|
180
|
+
async getPathInfo(): Promise<{
|
|
181
|
+
detectedPath: string | null;
|
|
182
|
+
isAvailable: boolean;
|
|
183
|
+
version?: string;
|
|
184
|
+
}> {
|
|
185
|
+
return {
|
|
186
|
+
detectedPath: "core-library",
|
|
187
|
+
isAvailable: true,
|
|
188
|
+
version: "2.0.0-core",
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Publish a tool (requires authentication)
|
|
194
|
+
*/
|
|
195
|
+
async publishTool(
|
|
196
|
+
tool: EnactTool,
|
|
197
|
+
): Promise<{ success: boolean; message: string }> {
|
|
198
|
+
return await this.core.publishTool(tool);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Create and export singleton instance
|
|
203
|
+
export const mcpCoreService = new McpCoreService();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './McpCoreService';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
// src/types.ts - Type definitions for Enact CLI Core
|
|
2
|
+
export interface EnactTool {
|
|
3
|
+
// REQUIRED FIELDS
|
|
4
|
+
name: string; // Tool identifier with hierarchical path
|
|
5
|
+
description: string; // Human-readable description
|
|
6
|
+
command: string; // Shell command to execute with version pins
|
|
7
|
+
|
|
8
|
+
// RECOMMENDED FIELDS
|
|
9
|
+
timeout?: string; // Go duration format: "30s", "5m", "1h" (default: "30s")
|
|
10
|
+
tags?: string[]; // Tags for search and categorization
|
|
11
|
+
license?: string; // SPDX License identifier (e.g., "MIT", "Apache-2.0")
|
|
12
|
+
outputSchema?: JSONSchemaDefinition; // Output structure as JSON Schema (strongly recommended)
|
|
13
|
+
|
|
14
|
+
// OPTIONAL FIELDS
|
|
15
|
+
enact?: string; // Protocol version (e.g., "1.0.0")
|
|
16
|
+
version?: string; // Tool definition version for tracking changes
|
|
17
|
+
namespace?: string; // Environment variable namespace (deprecated, use name hierarchy)
|
|
18
|
+
|
|
19
|
+
// Resource requirements
|
|
20
|
+
resources?: {
|
|
21
|
+
memory?: string; // System memory needed (e.g., "16Gi", "32Gi")
|
|
22
|
+
gpu?: string; // GPU memory needed (e.g., "24Gi", "48Gi")
|
|
23
|
+
disk?: string; // Disk space needed (e.g., "100Gi", "500Gi")
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Environment variables
|
|
27
|
+
env?: Record<
|
|
28
|
+
string,
|
|
29
|
+
{
|
|
30
|
+
description: string; // What this variable is for (required)
|
|
31
|
+
source: string; // Where to get this value (required)
|
|
32
|
+
required: boolean; // Whether this is required (required)
|
|
33
|
+
default?: string; // Default value if not set (optional)
|
|
34
|
+
}
|
|
35
|
+
>;
|
|
36
|
+
|
|
37
|
+
// Input/Output JSON Schemas
|
|
38
|
+
inputSchema?: JSONSchemaDefinition;
|
|
39
|
+
|
|
40
|
+
// Documentation and Testing
|
|
41
|
+
doc?: string; // Markdown documentation
|
|
42
|
+
authors?: Array<{
|
|
43
|
+
name: string; // Author name (required)
|
|
44
|
+
email?: string; // Author email (optional)
|
|
45
|
+
url?: string; // Author website (optional)
|
|
46
|
+
}>;
|
|
47
|
+
|
|
48
|
+
examples?: Array<{
|
|
49
|
+
input: Record<string, any>; // Input parameters
|
|
50
|
+
output?: any; // Expected output
|
|
51
|
+
description?: string; // Test description
|
|
52
|
+
}>;
|
|
53
|
+
|
|
54
|
+
// Behavior Annotations (MCP-aligned, all default to false)
|
|
55
|
+
annotations?: {
|
|
56
|
+
title?: string; // Human-readable display name
|
|
57
|
+
readOnlyHint?: boolean; // No environment modifications
|
|
58
|
+
destructiveHint?: boolean; // May make irreversible changes
|
|
59
|
+
idempotentHint?: boolean; // Multiple calls = single call
|
|
60
|
+
openWorldHint?: boolean; // Interacts with external systems
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Security
|
|
64
|
+
signature?: {
|
|
65
|
+
algorithm: string; // Hash algorithm: "sha256"
|
|
66
|
+
type: string; // Signature type: "ecdsa-p256"
|
|
67
|
+
signer: string; // Signer identifier
|
|
68
|
+
created: string; // ISO timestamp
|
|
69
|
+
value: string; // Base64 encoded signature
|
|
70
|
+
role?: string; // Optional description of the signer
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Multi-signature support (new format)
|
|
74
|
+
signatures?: Record<
|
|
75
|
+
string,
|
|
76
|
+
{
|
|
77
|
+
algorithm: string; // Hash algorithm: "sha256"
|
|
78
|
+
type: string; // Signature type: "ecdsa-p256"
|
|
79
|
+
signer: string; // Signer identifier
|
|
80
|
+
created: string; // ISO timestamp
|
|
81
|
+
value: string; // Base64 encoded signature
|
|
82
|
+
role?: string; // Optional description of the signer (e.g., "author", "maintainer")
|
|
83
|
+
}
|
|
84
|
+
>;
|
|
85
|
+
|
|
86
|
+
// Extensions pattern (x-prefixed fields)
|
|
87
|
+
[key: string]: any; // Allow x- prefixed extension fields
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// JSON Schema type definitions
|
|
91
|
+
export interface JSONSchemaDefinition {
|
|
92
|
+
type?: string | string[]; // JSON Schema type(s)
|
|
93
|
+
description?: string; // Human-readable description
|
|
94
|
+
format?: string; // Format specifier (e.g., "email", "date-time")
|
|
95
|
+
default?: any; // Default value
|
|
96
|
+
enum?: any[]; // Enumeration of possible values
|
|
97
|
+
const?: any; // Constant value
|
|
98
|
+
|
|
99
|
+
// String validations
|
|
100
|
+
pattern?: string; // Regular expression pattern
|
|
101
|
+
minLength?: number; // Minimum string length
|
|
102
|
+
maxLength?: number; // Maximum string length
|
|
103
|
+
|
|
104
|
+
// Number validations
|
|
105
|
+
minimum?: number; // Minimum value
|
|
106
|
+
maximum?: number; // Maximum value
|
|
107
|
+
exclusiveMinimum?: number; // Exclusive minimum
|
|
108
|
+
exclusiveMaximum?: number; // Exclusive maximum
|
|
109
|
+
multipleOf?: number; // Multiple of
|
|
110
|
+
|
|
111
|
+
// Array validations
|
|
112
|
+
items?: JSONSchemaDefinition | JSONSchemaDefinition[]; // Items schema
|
|
113
|
+
minItems?: number; // Minimum items
|
|
114
|
+
maxItems?: number; // Maximum items
|
|
115
|
+
uniqueItems?: boolean; // Items must be unique
|
|
116
|
+
|
|
117
|
+
// Object validations
|
|
118
|
+
properties?: Record<string, JSONSchemaDefinition>; // Properties
|
|
119
|
+
required?: string[]; // Required properties
|
|
120
|
+
additionalProperties?: JSONSchemaDefinition | boolean; // Additional properties
|
|
121
|
+
|
|
122
|
+
// Combiners
|
|
123
|
+
allOf?: JSONSchemaDefinition[]; // All of these schemas
|
|
124
|
+
anyOf?: JSONSchemaDefinition[]; // Any of these schemas
|
|
125
|
+
oneOf?: JSONSchemaDefinition[]; // Exactly one of these schemas
|
|
126
|
+
not?: JSONSchemaDefinition; // Not this schema
|
|
127
|
+
|
|
128
|
+
// Other
|
|
129
|
+
definitions?: Record<string, JSONSchemaDefinition>; // Definitions
|
|
130
|
+
$ref?: string; // JSON Schema reference
|
|
131
|
+
$id?: string; // Schema ID
|
|
132
|
+
$schema?: string; // Schema version
|
|
133
|
+
|
|
134
|
+
// Custom extensions
|
|
135
|
+
[key: string]: any; // Additional properties
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface ExecutionResult {
|
|
139
|
+
success: boolean;
|
|
140
|
+
output?: any; // Command output/result
|
|
141
|
+
error?: {
|
|
142
|
+
message: string;
|
|
143
|
+
code?: string;
|
|
144
|
+
details?: any;
|
|
145
|
+
};
|
|
146
|
+
metadata: {
|
|
147
|
+
executionId: string;
|
|
148
|
+
toolName: string; // Changed from toolId
|
|
149
|
+
version?: string;
|
|
150
|
+
executedAt: string;
|
|
151
|
+
environment: string;
|
|
152
|
+
timeout?: string;
|
|
153
|
+
command?: string; // The actual command that was executed
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Execution environment interface
|
|
158
|
+
export interface ExecutionEnvironment {
|
|
159
|
+
vars: Record<string, any>; // Environment variables
|
|
160
|
+
resources?: {
|
|
161
|
+
memory?: string;
|
|
162
|
+
gpu?: string;
|
|
163
|
+
disk?: string;
|
|
164
|
+
timeout?: string;
|
|
165
|
+
};
|
|
166
|
+
namespace?: string; // Environment variable namespace
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Updated execution provider interface
|
|
170
|
+
export abstract class ExecutionProvider {
|
|
171
|
+
abstract setup(tool: EnactTool): Promise<boolean>;
|
|
172
|
+
abstract execute(
|
|
173
|
+
tool: EnactTool,
|
|
174
|
+
inputs: Record<string, any>,
|
|
175
|
+
environment: ExecutionEnvironment,
|
|
176
|
+
): Promise<ExecutionResult>;
|
|
177
|
+
abstract cleanup(): Promise<boolean>;
|
|
178
|
+
abstract resolveEnvironmentVariables(
|
|
179
|
+
envConfig: Record<string, any>,
|
|
180
|
+
namespace?: string,
|
|
181
|
+
): Promise<Record<string, any>>;
|
|
182
|
+
|
|
183
|
+
// New method for command execution
|
|
184
|
+
abstract executeCommand(
|
|
185
|
+
command: string,
|
|
186
|
+
inputs: Record<string, any>,
|
|
187
|
+
environment: ExecutionEnvironment,
|
|
188
|
+
timeout?: string,
|
|
189
|
+
): Promise<{ stdout: string; stderr: string; exitCode: number }>;
|
|
190
|
+
}
|