@nobulex/mcp 0.1.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/dist/index.js ADDED
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ PRESETS: () => PRESETS,
24
+ SteleGuard: () => SteleGuard
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+ var import_crypto = require("@nobulex/crypto");
28
+ var import_ccl = require("@nobulex/ccl");
29
+ var import_core = require("@nobulex/core");
30
+ var import_enforcement = require("@nobulex/enforcement");
31
+ var import_identity = require("@nobulex/identity");
32
+ var import_reputation = require("@nobulex/reputation");
33
+ var import_proof = require("@nobulex/proof");
34
+
35
+ // src/presets.ts
36
+ var PRESETS = {
37
+ "standard:data-isolation": `permit file.read on '/data/**'
38
+ permit tool.read_file on '/data/**'
39
+ permit tool.* on '/data/**'
40
+ deny file.write on '**' severity high
41
+ deny network.send on '**' severity critical
42
+ deny network.send on '**' when payload.contains_pii = true severity critical
43
+ require audit.log on '**' severity critical
44
+ limit api.call 100 per 60 seconds`,
45
+ "standard:read-write": `permit file.read on '/data/**'
46
+ permit file.write on '/output/**'
47
+ deny file.write on '/system/**' severity critical
48
+ deny network.send on '**' severity high
49
+ deny network.send on '**' when payload.contains_pii = true severity critical
50
+ require audit.log on '**' severity critical`,
51
+ "standard:network": `permit file.read on '/data/**'
52
+ permit file.write on '/output/**'
53
+ permit network.send on '**'
54
+ deny network.send on '**' when payload.contains_pii = true severity critical
55
+ deny file.write on '/system/**' severity critical
56
+ require audit.log on '**' severity critical
57
+ require encrypt.output on '**' when output.classification = 'sensitive' severity high
58
+ limit api.call 500 per 3600 seconds
59
+ limit network.send 100 per 60 seconds`,
60
+ "standard:minimal": `deny file.read on '**' severity high
61
+ deny file.write on '**' severity critical
62
+ deny network.send on '**' severity critical
63
+ require audit.log on '**' severity critical`
64
+ };
65
+
66
+ // src/index.ts
67
+ function resolveConstraints(constraints) {
68
+ const trimmed = constraints.trim();
69
+ if (trimmed in PRESETS) {
70
+ return PRESETS[trimmed];
71
+ }
72
+ return trimmed;
73
+ }
74
+ function toolAction(toolName) {
75
+ return `tool.${toolName}`;
76
+ }
77
+ function toolResource(toolName, args) {
78
+ for (const key of ["path", "file", "url", "uri", "resource", "target", "name"]) {
79
+ const val = args[key];
80
+ if (typeof val === "string" && val.length > 0) {
81
+ return val;
82
+ }
83
+ }
84
+ return `/tool/${toolName}`;
85
+ }
86
+ function extractSeverity(matchedRule) {
87
+ if (matchedRule && typeof matchedRule === "object" && "severity" in matchedRule && typeof matchedRule.severity === "string") {
88
+ return matchedRule.severity;
89
+ }
90
+ return "medium";
91
+ }
92
+ function extractConstraint(matchedRule) {
93
+ if (matchedRule && typeof matchedRule === "object" && "type" in matchedRule) {
94
+ const rule = matchedRule;
95
+ const type = rule.type;
96
+ const action = rule.action ?? "*";
97
+ const resource = rule.resource ?? "*";
98
+ return `${type} ${action} on '${resource}'`;
99
+ }
100
+ return "default deny (no matching permit rule)";
101
+ }
102
+ var SteleGuard = class _SteleGuard {
103
+ // Private constructor - use static factory methods
104
+ constructor() {
105
+ }
106
+ /**
107
+ * Wrap an MCP server with Stele accountability using constraint text
108
+ * (either a preset name or raw CCL).
109
+ *
110
+ * Generates a keypair if one is not provided, creates an agent identity,
111
+ * builds a covenant document, and returns a wrapped server that intercepts
112
+ * every tool call through the constraint monitor.
113
+ */
114
+ static async wrap(server, options) {
115
+ const constraintSource = resolveConstraints(options.constraints);
116
+ (0, import_ccl.parse)(constraintSource);
117
+ const operatorKeyPair = options.operatorKeyPair ?? await (0, import_crypto.generateKeyPair)();
118
+ const model = options.model ?? {
119
+ provider: "unknown",
120
+ modelId: "unknown",
121
+ attestationType: "self_reported"
122
+ };
123
+ const identity = await (0, import_identity.createIdentity)({
124
+ operatorKeyPair,
125
+ operatorIdentifier: options.agentIdentifier,
126
+ model,
127
+ capabilities: (server.tools ?? []).map((t) => toolAction(t.name)),
128
+ deployment: {
129
+ runtime: "process"
130
+ }
131
+ });
132
+ const covenant = await (0, import_core.buildCovenant)({
133
+ issuer: {
134
+ id: options.agentIdentifier ?? operatorKeyPair.publicKeyHex,
135
+ publicKey: operatorKeyPair.publicKeyHex,
136
+ role: "issuer"
137
+ },
138
+ beneficiary: {
139
+ id: identity.id,
140
+ publicKey: operatorKeyPair.publicKeyHex,
141
+ role: "beneficiary"
142
+ },
143
+ constraints: constraintSource,
144
+ privateKey: operatorKeyPair.privateKey,
145
+ enforcement: {
146
+ type: "monitor",
147
+ config: { mode: options.mode ?? "enforce" }
148
+ },
149
+ proof: {
150
+ type: options.proofType ?? "audit_log",
151
+ config: {}
152
+ }
153
+ });
154
+ const monitor = new import_enforcement.Monitor(covenant.id, constraintSource, {
155
+ mode: options.mode ?? "enforce"
156
+ });
157
+ return _SteleGuard.buildWrappedServer(
158
+ server,
159
+ monitor,
160
+ identity,
161
+ covenant,
162
+ operatorKeyPair,
163
+ options
164
+ );
165
+ }
166
+ /**
167
+ * Wrap an MCP server using a pre-built covenant document.
168
+ *
169
+ * This is useful when the covenant has been created externally
170
+ * (e.g. by an orchestrator or governance system) and should be
171
+ * used as-is without re-building.
172
+ */
173
+ static async fromCovenant(server, covenant, operatorKeyPair) {
174
+ const identity = await (0, import_identity.createIdentity)({
175
+ operatorKeyPair,
176
+ model: {
177
+ provider: "unknown",
178
+ modelId: "unknown",
179
+ attestationType: "self_reported"
180
+ },
181
+ capabilities: (server.tools ?? []).map((t) => toolAction(t.name)),
182
+ deployment: {
183
+ runtime: "process"
184
+ }
185
+ });
186
+ const mode = covenant.enforcement?.config?.mode === "log_only" ? "log_only" : "enforce";
187
+ const monitor = new import_enforcement.Monitor(covenant.id, covenant.constraints, {
188
+ mode
189
+ });
190
+ return _SteleGuard.buildWrappedServer(
191
+ server,
192
+ monitor,
193
+ identity,
194
+ covenant,
195
+ operatorKeyPair,
196
+ {}
197
+ );
198
+ }
199
+ /**
200
+ * Internal method to build the wrapped server proxy from all
201
+ * the initialized components.
202
+ */
203
+ static buildWrappedServer(server, monitor, identity, covenant, operatorKeyPair, options) {
204
+ let totalToolCalls = 0;
205
+ let hasViolations = false;
206
+ let violationSeverity;
207
+ let firstCallTime;
208
+ let lastReceipt = null;
209
+ const interceptedHandleToolCall = async (name, args) => {
210
+ const callStart = Date.now();
211
+ if (firstCallTime === void 0) {
212
+ firstCallTime = callStart;
213
+ }
214
+ totalToolCalls++;
215
+ const action = toolAction(name);
216
+ const resource = toolResource(name, args);
217
+ const now = (0, import_crypto.timestamp)();
218
+ let permitted = true;
219
+ let result;
220
+ try {
221
+ await monitor.evaluate(action, resource, args);
222
+ } catch (err) {
223
+ permitted = false;
224
+ const severity = extractSeverity(
225
+ err && typeof err === "object" && "matchedRule" in err ? err.matchedRule : void 0
226
+ );
227
+ const constraint = extractConstraint(
228
+ err && typeof err === "object" && "matchedRule" in err ? err.matchedRule : void 0
229
+ );
230
+ hasViolations = true;
231
+ violationSeverity = severity;
232
+ if (options.onViolation) {
233
+ const details = {
234
+ toolName: name,
235
+ action,
236
+ resource,
237
+ constraint,
238
+ severity,
239
+ timestamp: now
240
+ };
241
+ options.onViolation(details);
242
+ }
243
+ if (options.onToolCall) {
244
+ const callEnd2 = Date.now();
245
+ const details = {
246
+ toolName: name,
247
+ action,
248
+ resource,
249
+ permitted: false,
250
+ timestamp: now,
251
+ durationMs: callEnd2 - callStart
252
+ };
253
+ options.onToolCall(details);
254
+ }
255
+ await updateReceipt(
256
+ covenant,
257
+ identity,
258
+ operatorKeyPair,
259
+ callStart,
260
+ hasViolations,
261
+ violationSeverity,
262
+ lastReceipt
263
+ ).then((r) => {
264
+ lastReceipt = r;
265
+ });
266
+ throw err;
267
+ }
268
+ if (server.handleToolCall) {
269
+ result = await server.handleToolCall(name, args);
270
+ } else {
271
+ result = void 0;
272
+ }
273
+ const callEnd = Date.now();
274
+ if (options.onToolCall) {
275
+ const details = {
276
+ toolName: name,
277
+ action,
278
+ resource,
279
+ permitted: true,
280
+ timestamp: now,
281
+ durationMs: callEnd - callStart
282
+ };
283
+ options.onToolCall(details);
284
+ }
285
+ lastReceipt = await updateReceipt(
286
+ covenant,
287
+ identity,
288
+ operatorKeyPair,
289
+ callStart,
290
+ hasViolations,
291
+ violationSeverity,
292
+ lastReceipt
293
+ );
294
+ return result;
295
+ };
296
+ const wrapped = /* @__PURE__ */ Object.create(null);
297
+ for (const key of Object.keys(server)) {
298
+ if (key === "handleToolCall") {
299
+ continue;
300
+ }
301
+ wrapped[key] = server[key];
302
+ }
303
+ if (server.tools) {
304
+ wrapped.tools = server.tools;
305
+ }
306
+ wrapped.handleToolCall = interceptedHandleToolCall;
307
+ wrapped.getMonitor = () => monitor;
308
+ wrapped.getIdentity = () => identity;
309
+ wrapped.getAuditLog = () => monitor.getAuditLog();
310
+ wrapped.generateProof = async () => {
311
+ const auditLog = monitor.getAuditLog();
312
+ const auditEntries = auditLog.entries.map(
313
+ (entry) => ({
314
+ action: entry.action,
315
+ resource: entry.resource,
316
+ outcome: entry.outcome,
317
+ timestamp: entry.timestamp,
318
+ hash: entry.hash
319
+ })
320
+ );
321
+ return (0, import_proof.generateComplianceProof)({
322
+ covenantId: covenant.id,
323
+ constraints: covenant.constraints,
324
+ auditEntries
325
+ });
326
+ };
327
+ wrapped.getReceipt = () => lastReceipt;
328
+ wrapped.getCovenant = () => covenant;
329
+ return wrapped;
330
+ }
331
+ };
332
+ async function updateReceipt(covenant, identity, operatorKeyPair, callStartTime, hasViolations, violationSeverity, previousReceipt) {
333
+ const durationMs = Date.now() - callStartTime;
334
+ let outcome;
335
+ let breachSeverity;
336
+ if (hasViolations) {
337
+ outcome = "breached";
338
+ breachSeverity = violationSeverity ?? "medium";
339
+ } else {
340
+ outcome = "fulfilled";
341
+ }
342
+ const proofHash = (0, import_crypto.sha256Object)({
343
+ covenantId: covenant.id,
344
+ identityId: identity.id,
345
+ timestamp: (0, import_crypto.timestamp)()
346
+ });
347
+ const receipt = await (0, import_reputation.createReceipt)(
348
+ covenant.id,
349
+ identity.id,
350
+ operatorKeyPair.publicKeyHex,
351
+ outcome,
352
+ proofHash,
353
+ durationMs,
354
+ operatorKeyPair,
355
+ previousReceipt?.receiptHash ?? null,
356
+ breachSeverity
357
+ );
358
+ return receipt;
359
+ }
360
+ // Annotate the CommonJS export names for ESM import in node:
361
+ 0 && (module.exports = {
362
+ PRESETS,
363
+ SteleGuard
364
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,338 @@
1
+ // src/index.ts
2
+ import { generateKeyPair, timestamp, sha256Object } from "@nobulex/crypto";
3
+ import { parse } from "@nobulex/ccl";
4
+ import { buildCovenant } from "@nobulex/core";
5
+ import { Monitor } from "@nobulex/enforcement";
6
+ import { createIdentity } from "@nobulex/identity";
7
+ import { createReceipt } from "@nobulex/reputation";
8
+ import { generateComplianceProof } from "@nobulex/proof";
9
+
10
+ // src/presets.ts
11
+ var PRESETS = {
12
+ "standard:data-isolation": `permit file.read on '/data/**'
13
+ permit tool.read_file on '/data/**'
14
+ permit tool.* on '/data/**'
15
+ deny file.write on '**' severity high
16
+ deny network.send on '**' severity critical
17
+ deny network.send on '**' when payload.contains_pii = true severity critical
18
+ require audit.log on '**' severity critical
19
+ limit api.call 100 per 60 seconds`,
20
+ "standard:read-write": `permit file.read on '/data/**'
21
+ permit file.write on '/output/**'
22
+ deny file.write on '/system/**' severity critical
23
+ deny network.send on '**' severity high
24
+ deny network.send on '**' when payload.contains_pii = true severity critical
25
+ require audit.log on '**' severity critical`,
26
+ "standard:network": `permit file.read on '/data/**'
27
+ permit file.write on '/output/**'
28
+ permit network.send on '**'
29
+ deny network.send on '**' when payload.contains_pii = true severity critical
30
+ deny file.write on '/system/**' severity critical
31
+ require audit.log on '**' severity critical
32
+ require encrypt.output on '**' when output.classification = 'sensitive' severity high
33
+ limit api.call 500 per 3600 seconds
34
+ limit network.send 100 per 60 seconds`,
35
+ "standard:minimal": `deny file.read on '**' severity high
36
+ deny file.write on '**' severity critical
37
+ deny network.send on '**' severity critical
38
+ require audit.log on '**' severity critical`
39
+ };
40
+
41
+ // src/index.ts
42
+ function resolveConstraints(constraints) {
43
+ const trimmed = constraints.trim();
44
+ if (trimmed in PRESETS) {
45
+ return PRESETS[trimmed];
46
+ }
47
+ return trimmed;
48
+ }
49
+ function toolAction(toolName) {
50
+ return `tool.${toolName}`;
51
+ }
52
+ function toolResource(toolName, args) {
53
+ for (const key of ["path", "file", "url", "uri", "resource", "target", "name"]) {
54
+ const val = args[key];
55
+ if (typeof val === "string" && val.length > 0) {
56
+ return val;
57
+ }
58
+ }
59
+ return `/tool/${toolName}`;
60
+ }
61
+ function extractSeverity(matchedRule) {
62
+ if (matchedRule && typeof matchedRule === "object" && "severity" in matchedRule && typeof matchedRule.severity === "string") {
63
+ return matchedRule.severity;
64
+ }
65
+ return "medium";
66
+ }
67
+ function extractConstraint(matchedRule) {
68
+ if (matchedRule && typeof matchedRule === "object" && "type" in matchedRule) {
69
+ const rule = matchedRule;
70
+ const type = rule.type;
71
+ const action = rule.action ?? "*";
72
+ const resource = rule.resource ?? "*";
73
+ return `${type} ${action} on '${resource}'`;
74
+ }
75
+ return "default deny (no matching permit rule)";
76
+ }
77
+ var SteleGuard = class _SteleGuard {
78
+ // Private constructor - use static factory methods
79
+ constructor() {
80
+ }
81
+ /**
82
+ * Wrap an MCP server with Stele accountability using constraint text
83
+ * (either a preset name or raw CCL).
84
+ *
85
+ * Generates a keypair if one is not provided, creates an agent identity,
86
+ * builds a covenant document, and returns a wrapped server that intercepts
87
+ * every tool call through the constraint monitor.
88
+ */
89
+ static async wrap(server, options) {
90
+ const constraintSource = resolveConstraints(options.constraints);
91
+ parse(constraintSource);
92
+ const operatorKeyPair = options.operatorKeyPair ?? await generateKeyPair();
93
+ const model = options.model ?? {
94
+ provider: "unknown",
95
+ modelId: "unknown",
96
+ attestationType: "self_reported"
97
+ };
98
+ const identity = await createIdentity({
99
+ operatorKeyPair,
100
+ operatorIdentifier: options.agentIdentifier,
101
+ model,
102
+ capabilities: (server.tools ?? []).map((t) => toolAction(t.name)),
103
+ deployment: {
104
+ runtime: "process"
105
+ }
106
+ });
107
+ const covenant = await buildCovenant({
108
+ issuer: {
109
+ id: options.agentIdentifier ?? operatorKeyPair.publicKeyHex,
110
+ publicKey: operatorKeyPair.publicKeyHex,
111
+ role: "issuer"
112
+ },
113
+ beneficiary: {
114
+ id: identity.id,
115
+ publicKey: operatorKeyPair.publicKeyHex,
116
+ role: "beneficiary"
117
+ },
118
+ constraints: constraintSource,
119
+ privateKey: operatorKeyPair.privateKey,
120
+ enforcement: {
121
+ type: "monitor",
122
+ config: { mode: options.mode ?? "enforce" }
123
+ },
124
+ proof: {
125
+ type: options.proofType ?? "audit_log",
126
+ config: {}
127
+ }
128
+ });
129
+ const monitor = new Monitor(covenant.id, constraintSource, {
130
+ mode: options.mode ?? "enforce"
131
+ });
132
+ return _SteleGuard.buildWrappedServer(
133
+ server,
134
+ monitor,
135
+ identity,
136
+ covenant,
137
+ operatorKeyPair,
138
+ options
139
+ );
140
+ }
141
+ /**
142
+ * Wrap an MCP server using a pre-built covenant document.
143
+ *
144
+ * This is useful when the covenant has been created externally
145
+ * (e.g. by an orchestrator or governance system) and should be
146
+ * used as-is without re-building.
147
+ */
148
+ static async fromCovenant(server, covenant, operatorKeyPair) {
149
+ const identity = await createIdentity({
150
+ operatorKeyPair,
151
+ model: {
152
+ provider: "unknown",
153
+ modelId: "unknown",
154
+ attestationType: "self_reported"
155
+ },
156
+ capabilities: (server.tools ?? []).map((t) => toolAction(t.name)),
157
+ deployment: {
158
+ runtime: "process"
159
+ }
160
+ });
161
+ const mode = covenant.enforcement?.config?.mode === "log_only" ? "log_only" : "enforce";
162
+ const monitor = new Monitor(covenant.id, covenant.constraints, {
163
+ mode
164
+ });
165
+ return _SteleGuard.buildWrappedServer(
166
+ server,
167
+ monitor,
168
+ identity,
169
+ covenant,
170
+ operatorKeyPair,
171
+ {}
172
+ );
173
+ }
174
+ /**
175
+ * Internal method to build the wrapped server proxy from all
176
+ * the initialized components.
177
+ */
178
+ static buildWrappedServer(server, monitor, identity, covenant, operatorKeyPair, options) {
179
+ let totalToolCalls = 0;
180
+ let hasViolations = false;
181
+ let violationSeverity;
182
+ let firstCallTime;
183
+ let lastReceipt = null;
184
+ const interceptedHandleToolCall = async (name, args) => {
185
+ const callStart = Date.now();
186
+ if (firstCallTime === void 0) {
187
+ firstCallTime = callStart;
188
+ }
189
+ totalToolCalls++;
190
+ const action = toolAction(name);
191
+ const resource = toolResource(name, args);
192
+ const now = timestamp();
193
+ let permitted = true;
194
+ let result;
195
+ try {
196
+ await monitor.evaluate(action, resource, args);
197
+ } catch (err) {
198
+ permitted = false;
199
+ const severity = extractSeverity(
200
+ err && typeof err === "object" && "matchedRule" in err ? err.matchedRule : void 0
201
+ );
202
+ const constraint = extractConstraint(
203
+ err && typeof err === "object" && "matchedRule" in err ? err.matchedRule : void 0
204
+ );
205
+ hasViolations = true;
206
+ violationSeverity = severity;
207
+ if (options.onViolation) {
208
+ const details = {
209
+ toolName: name,
210
+ action,
211
+ resource,
212
+ constraint,
213
+ severity,
214
+ timestamp: now
215
+ };
216
+ options.onViolation(details);
217
+ }
218
+ if (options.onToolCall) {
219
+ const callEnd2 = Date.now();
220
+ const details = {
221
+ toolName: name,
222
+ action,
223
+ resource,
224
+ permitted: false,
225
+ timestamp: now,
226
+ durationMs: callEnd2 - callStart
227
+ };
228
+ options.onToolCall(details);
229
+ }
230
+ await updateReceipt(
231
+ covenant,
232
+ identity,
233
+ operatorKeyPair,
234
+ callStart,
235
+ hasViolations,
236
+ violationSeverity,
237
+ lastReceipt
238
+ ).then((r) => {
239
+ lastReceipt = r;
240
+ });
241
+ throw err;
242
+ }
243
+ if (server.handleToolCall) {
244
+ result = await server.handleToolCall(name, args);
245
+ } else {
246
+ result = void 0;
247
+ }
248
+ const callEnd = Date.now();
249
+ if (options.onToolCall) {
250
+ const details = {
251
+ toolName: name,
252
+ action,
253
+ resource,
254
+ permitted: true,
255
+ timestamp: now,
256
+ durationMs: callEnd - callStart
257
+ };
258
+ options.onToolCall(details);
259
+ }
260
+ lastReceipt = await updateReceipt(
261
+ covenant,
262
+ identity,
263
+ operatorKeyPair,
264
+ callStart,
265
+ hasViolations,
266
+ violationSeverity,
267
+ lastReceipt
268
+ );
269
+ return result;
270
+ };
271
+ const wrapped = /* @__PURE__ */ Object.create(null);
272
+ for (const key of Object.keys(server)) {
273
+ if (key === "handleToolCall") {
274
+ continue;
275
+ }
276
+ wrapped[key] = server[key];
277
+ }
278
+ if (server.tools) {
279
+ wrapped.tools = server.tools;
280
+ }
281
+ wrapped.handleToolCall = interceptedHandleToolCall;
282
+ wrapped.getMonitor = () => monitor;
283
+ wrapped.getIdentity = () => identity;
284
+ wrapped.getAuditLog = () => monitor.getAuditLog();
285
+ wrapped.generateProof = async () => {
286
+ const auditLog = monitor.getAuditLog();
287
+ const auditEntries = auditLog.entries.map(
288
+ (entry) => ({
289
+ action: entry.action,
290
+ resource: entry.resource,
291
+ outcome: entry.outcome,
292
+ timestamp: entry.timestamp,
293
+ hash: entry.hash
294
+ })
295
+ );
296
+ return generateComplianceProof({
297
+ covenantId: covenant.id,
298
+ constraints: covenant.constraints,
299
+ auditEntries
300
+ });
301
+ };
302
+ wrapped.getReceipt = () => lastReceipt;
303
+ wrapped.getCovenant = () => covenant;
304
+ return wrapped;
305
+ }
306
+ };
307
+ async function updateReceipt(covenant, identity, operatorKeyPair, callStartTime, hasViolations, violationSeverity, previousReceipt) {
308
+ const durationMs = Date.now() - callStartTime;
309
+ let outcome;
310
+ let breachSeverity;
311
+ if (hasViolations) {
312
+ outcome = "breached";
313
+ breachSeverity = violationSeverity ?? "medium";
314
+ } else {
315
+ outcome = "fulfilled";
316
+ }
317
+ const proofHash = sha256Object({
318
+ covenantId: covenant.id,
319
+ identityId: identity.id,
320
+ timestamp: timestamp()
321
+ });
322
+ const receipt = await createReceipt(
323
+ covenant.id,
324
+ identity.id,
325
+ operatorKeyPair.publicKeyHex,
326
+ outcome,
327
+ proofHash,
328
+ durationMs,
329
+ operatorKeyPair,
330
+ previousReceipt?.receiptHash ?? null,
331
+ breachSeverity
332
+ );
333
+ return receipt;
334
+ }
335
+ export {
336
+ PRESETS,
337
+ SteleGuard
338
+ };
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@nobulex/mcp",
3
+ "version": "0.1.0",
4
+ "sideEffects": false,
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "module": "dist/index.mjs",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "default": "./dist/index.mjs"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsup src/index.ts --format cjs,esm",
17
+ "bundle": "tsup src/index.ts --format cjs,esm",
18
+ "dev": "tsup src/index.ts --format cjs,esm --watch",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "dependencies": {
27
+ "@nobulex/crypto": "0.1.0",
28
+ "@nobulex/ccl": "0.1.0",
29
+ "@nobulex/core": "0.1.0",
30
+ "@nobulex/enforcement": "0.1.0",
31
+ "@nobulex/identity": "0.1.0",
32
+ "@nobulex/reputation": "0.1.0",
33
+ "@nobulex/proof": "0.1.0"
34
+ },
35
+ "license": "MIT",
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/agbusiness195/Stele.git",
45
+ "directory": "packages/mcp"
46
+ },
47
+ "keywords": [
48
+ "stele",
49
+ "covenant",
50
+ "ai-accountability"
51
+ ]
52
+ }