@vaultys/mcp-agent 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 VaultysID
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ # @vaultys/mcp-agent
2
+
3
+ **Policy-enforced MCP server powered by VaultysID** — cryptographic authorization and tamper-evident audit trail for every AI tool call.
4
+
5
+ Every action your AI agent takes is:
6
+ 1. **Authorized** against a signed policy bundle
7
+ 2. **Executed** only if allowed
8
+ 3. **Receipted** with a cryptographic signature for tamper-evident audit
9
+
10
+ ## Quick Start — 2 minutes to Claude Desktop
11
+
12
+ ### 1. Add to Claude Desktop
13
+
14
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
15
+
16
+ ```json
17
+ {
18
+ "mcpServers": {
19
+ "vaultys-agent": {
20
+ "command": "npx",
21
+ "args": ["-y", "@vaultys/mcp-agent"]
22
+ }
23
+ }
24
+ }
25
+ ```
26
+
27
+ That's it. Restart Claude Desktop — the server auto-generates a default policy on first run.
28
+
29
+ ### 2. (Optional) Set a workspace directory
30
+
31
+ By default the agent uses your current working directory. To restrict file access to a specific project:
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "vaultys-agent": {
37
+ "command": "npx",
38
+ "args": ["-y", "@vaultys/mcp-agent"],
39
+ "env": {
40
+ "WORKSPACE_ROOT": "/Users/you/projects/my-app"
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### 3. (Optional) Customize the policy
48
+
49
+ ```bash
50
+ npx @vaultys/mcp-agent init --workspace /path/to/project --hours 48
51
+ ```
52
+
53
+ This creates/updates the signed policy in `~/.vaultys-mcp/`.
54
+
55
+ ## What It Does
56
+
57
+ ```
58
+ ┌──────────────┐ ┌────────────────────────────────────┐
59
+ │ Claude / │◄──MCP──►│ @vaultys/mcp-agent │
60
+ │ Cursor / │ stdio │ │
61
+ │ any client │ │ ┌──────────────────────────────┐ │
62
+ │ │ │ │ Policy Middleware │ │
63
+ │ │ │ │ map tool → capability │ │
64
+ │ │ │ │ evaluate against policy │ │
65
+ │ │ │ │ sign receipt │ │
66
+ │ │ │ └──────────────────────────────┘ │
67
+ │ │ │ │
68
+ │ │ │ Tools: │
69
+ │ │ │ read_file → fs.read:path │
70
+ │ │ │ write_file → fs.write:path │
71
+ │ │ │ list_directory → fs.list:path │
72
+ │ │ │ run_command → proc.exec:bin │
73
+ │ │ │ fetch_url → net.egress:host │
74
+ │ │ │ │
75
+ │ │ │ Audit: ~/.vaultys-mcp/ + ./audit/ │
76
+ └──────────────┘ └────────────────────────────────────┘
77
+ ```
78
+
79
+ ### Policy Enforcement
80
+
81
+ Every tool call is mapped to a taxonomy capability and checked against the signed policy:
82
+
83
+ | Tool | Capability | Example Scope |
84
+ | ---------------- | ----------------- | ------------------------- |
85
+ | `read_file` | `fs.read` | `/workspace/src/index.ts` |
86
+ | `write_file` | `fs.write` | `/workspace/output.json` |
87
+ | `list_directory` | `fs.list` | `/workspace/src` |
88
+ | `run_command` | `proc.exec` | `ls`, `grep`, `cat` |
89
+ | `fetch_url` | `net.egress.http` | `api.example.com` |
90
+
91
+ Denied calls return an error message to the AI and are logged with a signed denial receipt.
92
+
93
+ ### Default Policy
94
+
95
+ Auto-generated on first run — allows:
96
+ - File read/write/list within `WORKSPACE_ROOT`
97
+ - Safe commands: `ls`, `cat`, `echo`, `wc`, `head`, `tail`, `grep`, `find`, `pwd`, `date`, `whoami`
98
+ - HTTP requests to any host
99
+ - Blocks: `secrets.*`, `pkg.system`, `proc.privilege`
100
+
101
+ ## CLI Commands
102
+
103
+ ```bash
104
+ # Start the MCP server (called by Claude Desktop via npx)
105
+ npx @vaultys/mcp-agent
106
+
107
+ # Interactive setup — customize policy, workspace, validity
108
+ npx @vaultys/mcp-agent init
109
+ npx @vaultys/mcp-agent init --workspace /path --hours 48
110
+
111
+ # Sign a custom policy
112
+ npx @vaultys/mcp-agent grant --policy custom.json --hours 2
113
+
114
+ # Verify the audit trail
115
+ npx @vaultys/mcp-agent audit
116
+ npx @vaultys/mcp-agent audit --tamper <job-id> # demo tampering detection
117
+ ```
118
+
119
+ Or using globally installed commands:
120
+
121
+ ```bash
122
+ vaultys-mcp-agent # start server
123
+ vaultys-mcp-init # setup
124
+ vaultys-mcp-grant # sign policy
125
+ vaultys-mcp-audit # verify receipts
126
+ ```
127
+
128
+ ## MCP Resources
129
+
130
+ The server exposes these resources that Claude can read:
131
+
132
+ | Resource URI | Description |
133
+ | --------------------------- | --------------------------- |
134
+ | `vaultys://policy/current` | Active signed policy (JSON) |
135
+ | `vaultys://identity/server` | Server DID and public key |
136
+ | `vaultys://receipts/list` | All receipt summaries |
137
+
138
+ ## Configuration
139
+
140
+ ### Environment Variables
141
+
142
+ | Variable | Default | Description |
143
+ | -------------------- | ----------------- | ------------------------------------------- |
144
+ | `WORKSPACE_ROOT` | Current directory | Root directory for file operations |
145
+ | `POLICY_FILE` | (auto-managed) | Path to a custom signed policy file |
146
+ | `AUTHORITY_FILE` | (auto-managed) | Path to authority identity for verification |
147
+ | `VAULTYS_CONFIG_DIR` | `~/.vaultys-mcp` | Configuration directory |
148
+
149
+ ### Config Directory (`~/.vaultys-mcp/`)
150
+
151
+ | File | Purpose |
152
+ | ------------------------- | ----------------------------------- |
153
+ | `server.identity.json` | Server's VaultysID (auto-generated) |
154
+ | `authority.secret.json` | Authority private key (keep safe!) |
155
+ | `authority.identity.json` | Authority public key |
156
+ | `policy.signed.json` | Active signed policy |
157
+
158
+ ### Custom Policy File
159
+
160
+ Create a JSON policy and sign it:
161
+
162
+ ```json
163
+ {
164
+ "version": "1.0",
165
+ "scopes": {
166
+ "fs.read": ["{{WORKSPACE}}/**"],
167
+ "fs.write": ["{{WORKSPACE}}/output/**"],
168
+ "fs.list": ["{{WORKSPACE}}/**"],
169
+ "proc.exec": ["ls", "cat", "grep"],
170
+ "net.egress.http": ["api.mycompany.com"]
171
+ },
172
+ "denied": ["secrets.*", "pkg.system"],
173
+ "constraints": {
174
+ "max_runtime": 60,
175
+ "no_shell_features": true
176
+ }
177
+ }
178
+ ```
179
+
180
+ `{{WORKSPACE}}` is replaced with the actual workspace path at signing time.
181
+
182
+ ```bash
183
+ vaultys-mcp-grant --policy my-policy.json --workspace /my/project --hours 8
184
+ ```
185
+
186
+ ## Audit Trail
187
+
188
+ Every tool call produces a signed receipt in `./audit/`:
189
+
190
+ ```json
191
+ {
192
+ "job_id": "a1b2c3d4-...",
193
+ "timestamp": "2025-02-12T...",
194
+ "tool": "read_file",
195
+ "decision": "allow",
196
+ "allowed_caps": ["fs.read:/workspace/README.md"],
197
+ "receipt": {
198
+ "intent_hash": "sha256...",
199
+ "policy_hash": "sha256...",
200
+ "exec": { "started": "...", "ended": "...", "exit_code": 0 },
201
+ "broker_signature": "<base64>"
202
+ }
203
+ }
204
+ ```
205
+
206
+ Verify the entire audit trail:
207
+
208
+ ```bash
209
+ vaultys-mcp-audit
210
+ ```
211
+
212
+ Tampered receipts are detected — the cryptographic signature becomes invalid.
213
+
214
+ ## Security Model
215
+
216
+ - **Server identity**: Ed25519 keypair generated on first run, persisted in `~/.vaultys-mcp/`
217
+ - **Authority identity**: Separate keypair that signs policies — can be held by a different person/system
218
+ - **Policy signing**: Authority signs the policy bundle; server verifies before loading
219
+ - **Intent signing**: Server signs each execution intent before policy evaluation
220
+ - **Receipt signing**: Server signs each execution outcome for tamper-evident audit
221
+ - **Scope matching**: File paths resolved to absolute paths; glob matching against policy patterns
222
+ - **Denied capabilities**: Explicit deny list checked before scope matching (deny wins)
223
+
224
+ ## Development
225
+
226
+ ```bash
227
+ git clone https://github.com/nicmusic/vaultysid
228
+ cd typescript/demos/mcp-agent
229
+ pnpm install
230
+
231
+ # Run tests (29 E2E tests)
232
+ pnpm test
233
+
234
+ # Start server directly (dev mode, no build needed)
235
+ pnpm start
236
+
237
+ # Sign a policy (dev mode)
238
+ pnpm grant-policy
239
+
240
+ # Build for production
241
+ pnpm build
242
+ ```
243
+
244
+ ## License
245
+
246
+ MIT
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-audit — Verify the cryptographic audit trail.
4
+ *
5
+ * Walks through all signed receipts and verifies broker signatures.
6
+ *
7
+ * Usage:
8
+ * vaultys-mcp-audit # verify all receipts
9
+ * vaultys-mcp-audit --tamper <job-id> # tamper then verify (demo)
10
+ * vaultys-mcp-audit --dir /path/to/audit # custom audit directory
11
+ */
12
+ export {};
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-audit — Verify the cryptographic audit trail.
4
+ *
5
+ * Walks through all signed receipts and verifies broker signatures.
6
+ *
7
+ * Usage:
8
+ * vaultys-mcp-audit # verify all receipts
9
+ * vaultys-mcp-audit --tamper <job-id> # tamper then verify (demo)
10
+ * vaultys-mcp-audit --dir /path/to/audit # custom audit directory
11
+ */
12
+ import * as fs from "node:fs";
13
+ import * as path from "node:path";
14
+ import { ExecutionManager, IdManager, MemoryStorage } from "@vaultys/id";
15
+ import { configPath } from "../src/autoInit.js";
16
+ // ── Parse args ──
17
+ const args = process.argv.slice(2);
18
+ function getArg(name, defaultValue) {
19
+ const idx = args.indexOf(`--${name}`);
20
+ if (idx !== -1 && args[idx + 1])
21
+ return args[idx + 1];
22
+ return defaultValue;
23
+ }
24
+ const AUDIT_DIR = path.resolve(getArg("dir", "audit"));
25
+ const tamperId = getArg("tamper", "");
26
+ async function main() {
27
+ console.log("╔══════════════════════════════════════════════════╗");
28
+ console.log("║ VaultysID Audit Trail Verifier ║");
29
+ console.log("╚══════════════════════════════════════════════════╝");
30
+ console.log();
31
+ // Load server identity for verification
32
+ let serverVaultysId = null;
33
+ const identityPath = configPath("server.identity.json");
34
+ if (fs.existsSync(identityPath)) {
35
+ const data = fs.readFileSync(identityPath, "utf-8");
36
+ const store = MemoryStorage().fromString(data);
37
+ const idm = await IdManager.fromStore(store);
38
+ if (idm) {
39
+ serverVaultysId = idm.vaultysId;
40
+ console.log(`Server DID: ${serverVaultysId.did}`);
41
+ }
42
+ }
43
+ // Fallback: try local server.identity.json
44
+ if (!serverVaultysId && fs.existsSync("server.identity.json")) {
45
+ const data = fs.readFileSync("server.identity.json", "utf-8");
46
+ const store = MemoryStorage().fromString(data);
47
+ const idm = await IdManager.fromStore(store);
48
+ if (idm) {
49
+ serverVaultysId = idm.vaultysId;
50
+ console.log(`Server DID: ${serverVaultysId.did}`);
51
+ }
52
+ }
53
+ if (!serverVaultysId) {
54
+ console.error("⚠ Cannot load server identity — signature verification disabled");
55
+ }
56
+ console.log();
57
+ // Load receipts
58
+ if (!fs.existsSync(AUDIT_DIR)) {
59
+ console.log("No audit records found. Run some tool calls first!");
60
+ return;
61
+ }
62
+ const files = fs.readdirSync(AUDIT_DIR).filter((f) => f.endsWith(".json")).sort();
63
+ if (files.length === 0) {
64
+ console.log("No audit records found. Run some tool calls first!");
65
+ return;
66
+ }
67
+ console.log(`Found ${files.length} receipt(s)\n`);
68
+ // Optionally tamper
69
+ if (tamperId) {
70
+ const tamperFile = path.join(AUDIT_DIR, `${tamperId}.json`);
71
+ if (fs.existsSync(tamperFile)) {
72
+ const record = JSON.parse(fs.readFileSync(tamperFile, "utf-8"));
73
+ record.receipt.exec.exit_code = 999;
74
+ fs.writeFileSync(tamperFile, JSON.stringify(record, null, 2));
75
+ console.log(`🔧 TAMPERED with receipt ${tamperId} (changed exit_code to 999)\n`);
76
+ }
77
+ else {
78
+ console.error(`⚠ Receipt ${tamperId} not found`);
79
+ }
80
+ }
81
+ let passed = 0;
82
+ let failed = 0;
83
+ let skipped = 0;
84
+ for (const file of files) {
85
+ const filePath = path.join(AUDIT_DIR, file);
86
+ let record;
87
+ try {
88
+ record = JSON.parse(fs.readFileSync(filePath, "utf-8"));
89
+ }
90
+ catch {
91
+ console.log(` ⚠ ${file}: invalid JSON`);
92
+ skipped++;
93
+ continue;
94
+ }
95
+ const receipt = record.receipt;
96
+ const jobId = record.job_id;
97
+ const decision = record.decision;
98
+ const tool = record.tool;
99
+ if (receipt.broker_signature && typeof receipt.broker_signature === "string") {
100
+ receipt.broker_signature = Buffer.from(receipt.broker_signature, "base64");
101
+ }
102
+ let verified = false;
103
+ let sigStatus = "⏭ no key";
104
+ if (serverVaultysId) {
105
+ verified = ExecutionManager.verifyReceipt(receipt, serverVaultysId);
106
+ sigStatus = verified ? "✅ VALID" : "❌ INVALID";
107
+ if (verified)
108
+ passed++;
109
+ else
110
+ failed++;
111
+ }
112
+ else {
113
+ skipped++;
114
+ }
115
+ const decisionIcon = decision === "allow" ? "🟢" : "🔴";
116
+ console.log(` ${sigStatus} ${decisionIcon} ${tool.padEnd(16)} ${jobId} ${record.timestamp}`);
117
+ if (!verified && serverVaultysId) {
118
+ console.log(` ⚠ Signature verification FAILED — possible tampering!`);
119
+ }
120
+ }
121
+ console.log();
122
+ console.log("─".repeat(52));
123
+ console.log(` Results: ${passed} verified, ${failed} FAILED, ${skipped} skipped`);
124
+ if (failed > 0) {
125
+ console.log();
126
+ console.log(" ⚠ TAMPERING DETECTED in one or more receipts!");
127
+ }
128
+ else if (passed > 0) {
129
+ console.log();
130
+ console.log(" ✅ All receipts verified — audit trail is intact.");
131
+ }
132
+ console.log();
133
+ }
134
+ main().catch((err) => {
135
+ console.error("Error:", err);
136
+ process.exit(1);
137
+ });
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-grant — Sign a custom policy for the MCP agent.
4
+ *
5
+ * Usage:
6
+ * vaultys-mcp-grant # default policy, 1 year
7
+ * vaultys-mcp-grant --policy custom.json --hours 2 # custom policy, 2 hours
8
+ * vaultys-mcp-grant --workspace /my/project --hours 48 # custom workspace
9
+ */
10
+ export {};
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-grant — Sign a custom policy for the MCP agent.
4
+ *
5
+ * Usage:
6
+ * vaultys-mcp-grant # default policy, 1 year
7
+ * vaultys-mcp-grant --policy custom.json --hours 2 # custom policy, 2 hours
8
+ * vaultys-mcp-grant --workspace /my/project --hours 48 # custom workspace
9
+ */
10
+ import * as fs from "node:fs";
11
+ import * as path from "node:path";
12
+ import { ensureConfigDir, configPath, loadOrCreateIdentity, } from "../src/autoInit.js";
13
+ import { ExecutionManager } from "@vaultys/id";
14
+ // ── Parse args ──
15
+ const args = process.argv.slice(2);
16
+ function getArg(name, defaultValue) {
17
+ const idx = args.indexOf(`--${name}`);
18
+ if (idx !== -1 && args[idx + 1])
19
+ return args[idx + 1];
20
+ return defaultValue;
21
+ }
22
+ const policyFile = getArg("policy", "");
23
+ const hours = parseInt(getArg("hours", String(24 * 365)), 10);
24
+ const workspaceRoot = path.resolve(getArg("workspace", process.cwd()));
25
+ async function main() {
26
+ console.log("╔══════════════════════════════════════════════════╗");
27
+ console.log("║ VaultysID MCP Agent — Grant Policy ║");
28
+ console.log("╚══════════════════════════════════════════════════╝");
29
+ console.log();
30
+ ensureConfigDir();
31
+ // 1. Load or create authority
32
+ const { idm: authorityIdm, created } = await loadOrCreateIdentity(configPath("authority.secret.json"));
33
+ if (created) {
34
+ console.log(`✓ Generated authority identity: ${authorityIdm.vaultysId.did}`);
35
+ }
36
+ else {
37
+ console.log(`✓ Loaded authority identity: ${authorityIdm.vaultysId.did}`);
38
+ }
39
+ // Export public identity
40
+ const vid = authorityIdm.vaultysId;
41
+ fs.writeFileSync(configPath("authority.identity.json"), JSON.stringify({
42
+ did: vid.did,
43
+ id: Buffer.from(vid.id).toString("base64"),
44
+ fingerprint: vid.fingerprint,
45
+ }, null, 2));
46
+ // 2. Load policy template
47
+ let policyTemplate;
48
+ if (policyFile && fs.existsSync(policyFile)) {
49
+ policyTemplate = JSON.parse(fs.readFileSync(policyFile, "utf-8"));
50
+ console.log(`✓ Loaded custom policy: ${policyFile}`);
51
+ }
52
+ else {
53
+ // Use built-in default
54
+ policyTemplate = {
55
+ version: "1.0",
56
+ scopes: {
57
+ "fs.read": ["{{WORKSPACE}}/**"],
58
+ "fs.write": ["{{WORKSPACE}}/**"],
59
+ "fs.list": ["{{WORKSPACE}}/**"],
60
+ "proc.exec": ["ls", "cat", "echo", "wc", "head", "tail", "grep", "find", "pwd", "date", "whoami"],
61
+ "net.egress.http": ["*"],
62
+ },
63
+ denied: ["secrets.*", "pkg.system", "proc.privilege"],
64
+ constraints: {
65
+ max_runtime: 300,
66
+ no_shell_features: true,
67
+ },
68
+ };
69
+ console.log("✓ Using default policy template");
70
+ }
71
+ // 3. Substitute {{WORKSPACE}} placeholder
72
+ if (policyTemplate.scopes && typeof policyTemplate.scopes === "object") {
73
+ const scopes = policyTemplate.scopes;
74
+ for (const [key, patterns] of Object.entries(scopes)) {
75
+ if (Array.isArray(patterns)) {
76
+ scopes[key] = patterns.map((p) => p.replace(/\{\{WORKSPACE\}\}/g, workspaceRoot));
77
+ }
78
+ }
79
+ }
80
+ // 4. Add time bounds
81
+ const now = Date.now();
82
+ const policy = {
83
+ ...policyTemplate,
84
+ not_before: now,
85
+ not_after: now + hours * 3600_000,
86
+ };
87
+ console.log(` Workspace: ${workspaceRoot}`);
88
+ console.log(` Valid from: ${new Date(now).toISOString()}`);
89
+ console.log(` Expires: ${new Date(now + hours * 3600_000).toISOString()}`);
90
+ console.log(` Duration: ${hours} hours`);
91
+ // 5. Sign
92
+ const em = new ExecutionManager(authorityIdm);
93
+ const signed = await em.signPolicy(policy);
94
+ // 6. Persist
95
+ const serializable = {
96
+ ...signed,
97
+ signature: signed.signature
98
+ ? Buffer.from(signed.signature).toString("base64")
99
+ : undefined,
100
+ };
101
+ fs.writeFileSync(configPath("policy.signed.json"), JSON.stringify(serializable, null, 2));
102
+ console.log();
103
+ console.log(`✓ Signed policy saved to: ${configPath("policy.signed.json")}`);
104
+ console.log();
105
+ console.log("Run 'npx @vaultys/mcp-agent' to start the server with this policy.");
106
+ }
107
+ main().catch((err) => {
108
+ console.error("Error:", err);
109
+ process.exit(1);
110
+ });
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-init — Interactive configuration for the MCP agent.
4
+ *
5
+ * Creates or updates configuration in ~/.vaultys-mcp/:
6
+ * - Server identity (auto-generated if missing)
7
+ * - Authority identity (auto-generated if missing)
8
+ * - Signed policy (customizable)
9
+ *
10
+ * Usage:
11
+ * npx @vaultys/mcp-agent init # interactive setup
12
+ * vaultys-mcp-init --hours 48 # 48-hour policy
13
+ * vaultys-mcp-init --workspace /my/dir # custom workspace root
14
+ */
15
+ export {};
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-init — Interactive configuration for the MCP agent.
4
+ *
5
+ * Creates or updates configuration in ~/.vaultys-mcp/:
6
+ * - Server identity (auto-generated if missing)
7
+ * - Authority identity (auto-generated if missing)
8
+ * - Signed policy (customizable)
9
+ *
10
+ * Usage:
11
+ * npx @vaultys/mcp-agent init # interactive setup
12
+ * vaultys-mcp-init --hours 48 # 48-hour policy
13
+ * vaultys-mcp-init --workspace /my/dir # custom workspace root
14
+ */
15
+ import * as path from "node:path";
16
+ import { ensureConfigDir, loadOrCreateIdentity, configPath, signAndPersistPolicy, } from "../src/autoInit.js";
17
+ // ── Parse args ──
18
+ const args = process.argv.slice(2);
19
+ function getArg(name, defaultValue) {
20
+ const idx = args.indexOf(`--${name}`);
21
+ if (idx !== -1 && args[idx + 1])
22
+ return args[idx + 1];
23
+ return defaultValue;
24
+ }
25
+ const hours = parseInt(getArg("hours", String(24 * 365)), 10);
26
+ const workspaceRoot = path.resolve(getArg("workspace", process.cwd()));
27
+ async function main() {
28
+ console.log("╔══════════════════════════════════════════════════╗");
29
+ console.log("║ VaultysID MCP Agent — Setup ║");
30
+ console.log("╚══════════════════════════════════════════════════╝");
31
+ console.log();
32
+ const dir = ensureConfigDir();
33
+ console.log(`Config directory: ${dir}`);
34
+ console.log();
35
+ // 1. Server identity
36
+ const { idm: serverIdm, created: serverCreated } = await loadOrCreateIdentity(configPath("server.identity.json"));
37
+ if (serverCreated) {
38
+ console.log(`✓ Generated server identity: ${serverIdm.vaultysId.did}`);
39
+ }
40
+ else {
41
+ console.log(`✓ Server identity exists: ${serverIdm.vaultysId.did}`);
42
+ }
43
+ // 2. Authority + Policy
44
+ const { signedPolicy, authorityIdm } = await signAndPersistPolicy(workspaceRoot, hours);
45
+ console.log(`✓ Authority DID: ${authorityIdm.vaultysId.did}`);
46
+ console.log(`✓ Policy signed (${hours} hours validity)`);
47
+ console.log(` Workspace: ${workspaceRoot}`);
48
+ if (signedPolicy.not_before) {
49
+ console.log(` Valid from: ${new Date(signedPolicy.not_before).toISOString()}`);
50
+ }
51
+ if (signedPolicy.not_after) {
52
+ console.log(` Expires: ${new Date(signedPolicy.not_after).toISOString()}`);
53
+ }
54
+ console.log();
55
+ console.log("┌──────────────────────────────────────────────────┐");
56
+ console.log("│ Setup complete! │");
57
+ console.log("├──────────────────────────────────────────────────┤");
58
+ console.log("│ │");
59
+ console.log("│ Add to Claude Desktop config: │");
60
+ console.log("│ │");
61
+ console.log('│ "mcpServers": { │');
62
+ console.log('│ "vaultys-agent": { │');
63
+ console.log('│ "command": "npx", │');
64
+ console.log('│ "args": ["@vaultys/mcp-agent"] │');
65
+ console.log("│ } │");
66
+ console.log("│ } │");
67
+ console.log("│ │");
68
+ console.log("│ Config file location (macOS): │");
69
+ console.log("│ ~/Library/Application Support/Claude/ │");
70
+ console.log("│ claude_desktop_config.json │");
71
+ console.log("│ │");
72
+ console.log("└──────────────────────────────────────────────────┘");
73
+ }
74
+ main().catch((err) => {
75
+ console.error("Error:", err);
76
+ process.exit(1);
77
+ });
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-agent — Start the policy-enforced MCP server.
4
+ *
5
+ * Usage:
6
+ * npx @vaultys/mcp-agent # zero-config, uses cwd
7
+ * WORKSPACE_ROOT=/my/project npx @vaultys/mcp-agent # custom workspace
8
+ */
9
+ import "../src/server.js";
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vaultys-mcp-agent — Start the policy-enforced MCP server.
4
+ *
5
+ * Usage:
6
+ * npx @vaultys/mcp-agent # zero-config, uses cwd
7
+ * WORKSPACE_ROOT=/my/project npx @vaultys/mcp-agent # custom workspace
8
+ */
9
+ import "../src/server.js";
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Grant Policy CLI
4
+ *
5
+ * Creates an authority identity and signs a policy bundle.
6
+ * Outputs:
7
+ * - policy.signed.json — the signed policy (loaded by the MCP server)
8
+ * - authority.identity.json — the authority's public key (for verification)
9
+ * - authority.secret.json — the authority's full identity (keep safe!)
10
+ *
11
+ * Usage:
12
+ * pnpm grant-policy # uses policy.example.json, 24h validity
13
+ * pnpm grant-policy -- --policy custom.json # custom policy file
14
+ * pnpm grant-policy -- --hours 2 # 2-hour validity window
15
+ */
16
+ export {};