@vaultys/mcp-agent 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/audit.js
CHANGED
|
@@ -96,8 +96,13 @@ async function main() {
|
|
|
96
96
|
const jobId = record.job_id;
|
|
97
97
|
const decision = record.decision;
|
|
98
98
|
const tool = record.tool;
|
|
99
|
-
if (receipt.broker_signature
|
|
100
|
-
|
|
99
|
+
if (receipt.broker_signature) {
|
|
100
|
+
if (typeof receipt.broker_signature === "string") {
|
|
101
|
+
receipt.broker_signature = Buffer.from(receipt.broker_signature, "base64");
|
|
102
|
+
}
|
|
103
|
+
else if (typeof receipt.broker_signature === "object" && receipt.broker_signature.data) {
|
|
104
|
+
receipt.broker_signature = Buffer.from(receipt.broker_signature.data);
|
|
105
|
+
}
|
|
101
106
|
}
|
|
102
107
|
let verified = false;
|
|
103
108
|
let sigStatus = "⏭ no key";
|
package/dist/src/audit.js
CHANGED
|
@@ -91,8 +91,13 @@ async function main() {
|
|
|
91
91
|
const decision = record.decision;
|
|
92
92
|
const tool = record.tool;
|
|
93
93
|
// Restore Buffer types for signature
|
|
94
|
-
if (receipt.broker_signature
|
|
95
|
-
|
|
94
|
+
if (receipt.broker_signature) {
|
|
95
|
+
if (typeof receipt.broker_signature === "string") {
|
|
96
|
+
receipt.broker_signature = Buffer.from(receipt.broker_signature, "base64");
|
|
97
|
+
}
|
|
98
|
+
else if (typeof receipt.broker_signature === "object" && receipt.broker_signature.data) {
|
|
99
|
+
receipt.broker_signature = Buffer.from(receipt.broker_signature.data);
|
|
100
|
+
}
|
|
96
101
|
}
|
|
97
102
|
let verified = false;
|
|
98
103
|
let sigStatus = "⏭ no key";
|
|
@@ -31,11 +31,13 @@ export interface CapabilityMapping {
|
|
|
31
31
|
* tools can resolve relative paths to absolute paths matching the policy globs.
|
|
32
32
|
*/
|
|
33
33
|
export declare const DEFAULT_TOOL_MAPPINGS: Record<string, CapabilityMapping>;
|
|
34
|
+
export declare function setAuditDir(dir: string): void;
|
|
34
35
|
export interface PolicyMiddlewareOptions {
|
|
35
36
|
serverIdManager: IdManager;
|
|
36
37
|
signedPolicy: PolicyBundle;
|
|
37
38
|
toolMappings?: Record<string, CapabilityMapping>;
|
|
38
39
|
workspaceRoot?: string;
|
|
40
|
+
auditDir?: string;
|
|
39
41
|
}
|
|
40
42
|
export interface ToolCallResult {
|
|
41
43
|
decision: "allow" | "deny";
|
|
@@ -79,7 +79,10 @@ function resolveWorkspacePath(raw, workspaceRoot) {
|
|
|
79
79
|
return path.join(workspaceRoot ?? "/workspace", raw);
|
|
80
80
|
}
|
|
81
81
|
// ── Audit persistence ──
|
|
82
|
-
|
|
82
|
+
let AUDIT_DIR = path.resolve("audit");
|
|
83
|
+
export function setAuditDir(dir) {
|
|
84
|
+
AUDIT_DIR = path.resolve(dir);
|
|
85
|
+
}
|
|
83
86
|
function ensureAuditDir() {
|
|
84
87
|
if (!fs.existsSync(AUDIT_DIR)) {
|
|
85
88
|
fs.mkdirSync(AUDIT_DIR, { recursive: true });
|
|
@@ -87,11 +90,18 @@ function ensureAuditDir() {
|
|
|
87
90
|
}
|
|
88
91
|
function persistReceipt(jobId, receipt, meta) {
|
|
89
92
|
ensureAuditDir();
|
|
93
|
+
// Serialize broker_signature as base64 string for JSON storage
|
|
94
|
+
const serializedReceipt = {
|
|
95
|
+
...receipt,
|
|
96
|
+
broker_signature: receipt.broker_signature
|
|
97
|
+
? Buffer.from(receipt.broker_signature).toString("base64")
|
|
98
|
+
: undefined,
|
|
99
|
+
};
|
|
90
100
|
const record = {
|
|
91
101
|
job_id: jobId,
|
|
92
102
|
timestamp: new Date().toISOString(),
|
|
93
103
|
...meta,
|
|
94
|
-
receipt,
|
|
104
|
+
receipt: serializedReceipt,
|
|
95
105
|
};
|
|
96
106
|
const filePath = path.join(AUDIT_DIR, `${jobId}.json`);
|
|
97
107
|
fs.writeFileSync(filePath, JSON.stringify(record, null, 2));
|
|
@@ -100,7 +110,10 @@ function persistReceipt(jobId, receipt, meta) {
|
|
|
100
110
|
* Create policy-enforced middleware that wraps MCP tool handlers.
|
|
101
111
|
*/
|
|
102
112
|
export function createPolicyMiddleware(options) {
|
|
103
|
-
const { serverIdManager, signedPolicy, toolMappings = DEFAULT_TOOL_MAPPINGS, workspaceRoot = process.cwd(), } = options;
|
|
113
|
+
const { serverIdManager, signedPolicy, toolMappings = DEFAULT_TOOL_MAPPINGS, workspaceRoot = process.cwd(), auditDir, } = options;
|
|
114
|
+
if (auditDir) {
|
|
115
|
+
setAuditDir(auditDir);
|
|
116
|
+
}
|
|
104
117
|
const em = new ExecutionManager(serverIdManager);
|
|
105
118
|
/**
|
|
106
119
|
* Wrap a tool call: evaluate policy, run handler if allowed, sign receipt.
|
package/dist/src/server.js
CHANGED
|
@@ -25,6 +25,7 @@ import { createPolicyMiddleware } from "./policyMiddleware.js";
|
|
|
25
25
|
import { registerFilesystemTools } from "./tools/filesystem.js";
|
|
26
26
|
import { registerShellTool } from "./tools/shell.js";
|
|
27
27
|
import { registerNetworkTool } from "./tools/network.js";
|
|
28
|
+
import { registerAuditTool } from "./tools/audit.js";
|
|
28
29
|
import { registerResources } from "./resources/index.js";
|
|
29
30
|
// ── Configuration ──
|
|
30
31
|
const WORKSPACE_ROOT = path.resolve(process.env.WORKSPACE_ROOT ?? process.cwd());
|
|
@@ -68,6 +69,7 @@ async function main() {
|
|
|
68
69
|
registerFilesystemTools(mcpServer, middleware, WORKSPACE_ROOT);
|
|
69
70
|
registerShellTool(mcpServer, middleware, WORKSPACE_ROOT);
|
|
70
71
|
registerNetworkTool(mcpServer, middleware);
|
|
72
|
+
registerAuditTool(mcpServer, serverIdm);
|
|
71
73
|
// 7. Register resources (audit trail, policy, identity)
|
|
72
74
|
registerResources(mcpServer, serverIdm, signedPolicy);
|
|
73
75
|
// 8. Connect via stdio transport
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit verification MCP tool — lets Claude verify the cryptographic audit trail.
|
|
3
|
+
*
|
|
4
|
+
* Tool:
|
|
5
|
+
* verify_audit — verify all signed receipts, report valid/invalid/tampered
|
|
6
|
+
*/
|
|
7
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
import type { IdManager } from "@vaultys/id";
|
|
9
|
+
export declare function registerAuditTool(server: McpServer, serverIdManager: IdManager): void;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit verification MCP tool — lets Claude verify the cryptographic audit trail.
|
|
3
|
+
*
|
|
4
|
+
* Tool:
|
|
5
|
+
* verify_audit — verify all signed receipts, report valid/invalid/tampered
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { ExecutionManager } from "@vaultys/id";
|
|
11
|
+
const AUDIT_DIR = path.resolve("audit");
|
|
12
|
+
function restoreSignature(receipt) {
|
|
13
|
+
if (receipt.broker_signature) {
|
|
14
|
+
if (typeof receipt.broker_signature === "string") {
|
|
15
|
+
receipt.broker_signature = Buffer.from(receipt.broker_signature, "base64");
|
|
16
|
+
}
|
|
17
|
+
else if (typeof receipt.broker_signature === "object" && receipt.broker_signature.data) {
|
|
18
|
+
receipt.broker_signature = Buffer.from(receipt.broker_signature.data);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function registerAuditTool(server, serverIdManager) {
|
|
23
|
+
server.tool("verify_audit", "Verify the cryptographic audit trail. Checks all signed receipts for tampering. Returns verification results for each receipt.", {
|
|
24
|
+
limit: z.number().optional().describe("Maximum number of recent receipts to verify (default: all)"),
|
|
25
|
+
}, async (args) => {
|
|
26
|
+
const serverVid = serverIdManager.vaultysId;
|
|
27
|
+
if (!fs.existsSync(AUDIT_DIR)) {
|
|
28
|
+
return {
|
|
29
|
+
content: [{ type: "text", text: "No audit directory found. No tool calls have been recorded yet." }],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const files = fs.readdirSync(AUDIT_DIR)
|
|
33
|
+
.filter((f) => f.endsWith(".json"))
|
|
34
|
+
.sort();
|
|
35
|
+
if (files.length === 0) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: "No audit receipts found. No tool calls have been recorded yet." }],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const limit = args.limit ?? files.length;
|
|
41
|
+
const toVerify = files.slice(-limit); // most recent N
|
|
42
|
+
let passed = 0;
|
|
43
|
+
let failed = 0;
|
|
44
|
+
let errors = 0;
|
|
45
|
+
const results = [];
|
|
46
|
+
for (const file of toVerify) {
|
|
47
|
+
const filePath = path.join(AUDIT_DIR, file);
|
|
48
|
+
let record;
|
|
49
|
+
try {
|
|
50
|
+
record = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
errors++;
|
|
54
|
+
results.push({
|
|
55
|
+
job_id: file.replace(".json", ""),
|
|
56
|
+
timestamp: "?",
|
|
57
|
+
tool: "?",
|
|
58
|
+
decision: "?",
|
|
59
|
+
verified: "error",
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
restoreSignature(record.receipt);
|
|
64
|
+
let verified = false;
|
|
65
|
+
try {
|
|
66
|
+
verified = ExecutionManager.verifyReceipt(record.receipt, serverVid);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
verified = false;
|
|
70
|
+
}
|
|
71
|
+
if (verified)
|
|
72
|
+
passed++;
|
|
73
|
+
else
|
|
74
|
+
failed++;
|
|
75
|
+
results.push({
|
|
76
|
+
job_id: record.job_id,
|
|
77
|
+
timestamp: record.timestamp,
|
|
78
|
+
tool: record.tool,
|
|
79
|
+
decision: record.decision,
|
|
80
|
+
verified,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const summary = {
|
|
84
|
+
total: files.length,
|
|
85
|
+
verified_count: toVerify.length,
|
|
86
|
+
passed,
|
|
87
|
+
failed,
|
|
88
|
+
errors,
|
|
89
|
+
integrity: failed === 0 && errors === 0 ? "INTACT" : "COMPROMISED",
|
|
90
|
+
server_did: serverVid.did,
|
|
91
|
+
results,
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
content: [{
|
|
95
|
+
type: "text",
|
|
96
|
+
text: JSON.stringify(summary, null, 2),
|
|
97
|
+
}],
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaultys/mcp-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Policy-enforced MCP server powered by VaultysID — cryptographic authorization and audit trail for every AI tool call",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"grant-policy": "tsx grant-policy.ts",
|
|
51
51
|
"srp-grant": "tsx srp-grant-policy.ts",
|
|
52
52
|
"audit": "tsx src/audit.ts",
|
|
53
|
-
"test": "tsx test
|
|
53
|
+
"test": "tsx test/e2e.test.ts",
|
|
54
54
|
"build": "tsc && chmod +x dist/bin/*.js"
|
|
55
55
|
}
|
|
56
56
|
}
|