@vaultys/mcp-agent 0.1.4 → 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.
|
@@ -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 });
|
|
@@ -107,7 +110,10 @@ function persistReceipt(jobId, receipt, meta) {
|
|
|
107
110
|
* Create policy-enforced middleware that wraps MCP tool handlers.
|
|
108
111
|
*/
|
|
109
112
|
export function createPolicyMiddleware(options) {
|
|
110
|
-
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
|
+
}
|
|
111
117
|
const em = new ExecutionManager(serverIdManager);
|
|
112
118
|
/**
|
|
113
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
|
}
|