argus-aml 0.0.0-stage → 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.
Files changed (3) hide show
  1. package/README.md +14 -2
  2. package/bin/init.js +114 -0
  3. package/package.json +7 -4
package/README.md CHANGED
@@ -1,3 +1,15 @@
1
- # Temporary Holding Version
1
+ # argus-aml
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Add the Argus API's compliance tools to your AI agent.
4
+
5
+ ```bash
6
+ npx argus-aml init
7
+ ```
8
+
9
+ This creates a sandbox key, then adds Argus to Claude Code and Cursor if it finds them. Sandbox results are invented and
10
+ cost nothing.
11
+
12
+ Use your live key with `npx argus-aml init --key ak_...`.
13
+
14
+ Your key is saved to `~/.config/argus/key`, readable only by you. For any other MCP client, point it at
15
+ `https://argus.unbackoffice.com/mcp` and send your key in the `X-API-Key` header.
package/bin/init.js ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // npx argus-aml init: get a sandbox key (or take --key) and add the Argus MCP server to the agents on this machine.
4
+ const fs = require("fs");
5
+ const os = require("os");
6
+ const path = require("path");
7
+ const { spawnSync } = require("child_process");
8
+
9
+ const API = (process.env.ARGUS_API_URL || "https://argus.unbackoffice.com").replace(/\/$/, "");
10
+ const MCP = API + "/mcp";
11
+ const ok = (s) => console.log("✓ " + s);
12
+ const fail = (s) => { console.error("✗ " + s); process.exit(1); };
13
+
14
+ function argValue(args, name) {
15
+ const i = args.indexOf(name);
16
+ if (i < 0) return "";
17
+ if (!args[i + 1]) fail(name + " needs a value");
18
+ return args[i + 1];
19
+ }
20
+
21
+ async function sandboxKey() {
22
+ let r;
23
+ try {
24
+ r = await fetch(API + "/v1/founder/sandbox-key", { method: "POST" });
25
+ } catch (e) {
26
+ fail("Couldn't reach " + API + ". Check your connection and try again.");
27
+ }
28
+ const d = await r.json().catch(() => ({}));
29
+ if (!r.ok || !d.api_key) fail(d.detail || "Couldn't create a sandbox key. Try again shortly.");
30
+ return d.api_key;
31
+ }
32
+
33
+ function savedKey() {
34
+ try {
35
+ return fs.readFileSync(path.join(os.homedir(), ".config", "argus", "key"), "utf8").trim();
36
+ } catch (e) {
37
+ return "";
38
+ }
39
+ }
40
+
41
+ function saveKey(key) {
42
+ const dir = path.join(os.homedir(), ".config", "argus");
43
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
44
+ const file = path.join(dir, "key");
45
+ fs.writeFileSync(file, key + "\n", { mode: 0o600 });
46
+ fs.chmodSync(file, 0o600);
47
+ return file;
48
+ }
49
+
50
+ function onPath(cmd) {
51
+ return spawnSync(process.platform === "win32" ? "where" : "which", [cmd], { stdio: "ignore" }).status === 0;
52
+ }
53
+
54
+ function addToClaude(key) {
55
+ if (!onPath("claude")) return false;
56
+ spawnSync("claude", ["mcp", "remove", "argus", "--scope", "user"], { stdio: "ignore" });
57
+ const r = spawnSync("claude", ["mcp", "add", "--transport", "http", "--scope", "user", "argus", MCP,
58
+ "--header", "X-API-Key: " + key], { encoding: "utf8" });
59
+ if (r.status !== 0) {
60
+ console.error("✗ Couldn't add Argus to Claude Code: " + ((r.stderr || "").replace(key, "***").trim() || "unknown error"));
61
+ return false;
62
+ }
63
+ return true;
64
+ }
65
+
66
+ function addToCursor(key) {
67
+ const dir = path.join(os.homedir(), ".cursor");
68
+ if (!fs.existsSync(dir)) return false;
69
+ const file = path.join(dir, "mcp.json");
70
+ let cfg = {};
71
+ if (fs.existsSync(file)) {
72
+ try {
73
+ cfg = JSON.parse(fs.readFileSync(file, "utf8"));
74
+ } catch (e) {
75
+ console.error("✗ Left " + file + " alone: it isn't valid JSON.");
76
+ return false;
77
+ }
78
+ }
79
+ cfg.mcpServers = { ...(cfg.mcpServers || {}), argus: { url: MCP, headers: { "X-API-Key": key } } };
80
+ fs.writeFileSync(file, JSON.stringify(cfg, null, 2) + "\n", { mode: 0o600 });
81
+ fs.chmodSync(file, 0o600);
82
+ return true;
83
+ }
84
+
85
+ async function main() {
86
+ const args = process.argv.slice(2);
87
+ if (args[0] !== "init") {
88
+ console.log("Usage: npx argus-aml init [--key ak_...]");
89
+ process.exit(args.length && !["-h", "--help"].includes(args[0]) ? 1 : 0);
90
+ }
91
+ // a key saved by an earlier run is kept: running init again must never swap a live key for a sandbox one
92
+ const given = argValue(args, "--key") || process.env.ARGUS_API_KEY || savedKey();
93
+ const key = given || (await sandboxKey());
94
+ ok(given ? "Using your API key" : "Sandbox key created");
95
+ const file = saveKey(key);
96
+ ok("Key saved to " + file);
97
+
98
+ const added = [];
99
+ if (addToClaude(key)) added.push("Claude Code");
100
+ if (addToCursor(key)) added.push("Cursor");
101
+ if (added.length) {
102
+ ok("Argus tools added to " + added.join(" and "));
103
+ } else {
104
+ console.log("\nNo supported agent found. Add this to any MCP client:");
105
+ console.log(" URL: " + MCP);
106
+ console.log(" Header: X-API-Key: (the key in " + file + ")");
107
+ }
108
+ if (added.length) console.log("\nRestart your agent, then try:");
109
+ else console.log("\nThen try:");
110
+ console.log(" Screen Sandbox Sanctioned and tell me what happens next.");
111
+ if (!given) console.log("\nSandbox results are invented. Ask for a live key at " + API + "/developers");
112
+ }
113
+
114
+ main().catch(() => fail("Something went wrong. Try again."));
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "argus-aml",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Add the Argus API's compliance tools to your AI agent.",
5
+ "bin": { "argus-aml": "bin/init.js" },
6
+ "files": ["bin", "README.md"],
7
+ "engines": { "node": ">=18" },
8
+ "license": "UNLICENSED"
9
+ }