@agentwares/agentguard 0.1.7 → 0.1.9
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/CHANGELOG.md +75 -0
- package/README.md +223 -16
- package/dist/audit-2YCMHMCP.js +17 -0
- package/dist/audit-2YCMHMCP.js.map +1 -0
- package/dist/chunk-3O6KWT3E.js +345 -0
- package/dist/chunk-3O6KWT3E.js.map +1 -0
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/chunk-5WRI5ZAA.js.map +1 -0
- package/dist/chunk-6S7LYVOC.js +1033 -0
- package/dist/chunk-6S7LYVOC.js.map +1 -0
- package/dist/chunk-6TUQD666.js +828 -0
- package/dist/chunk-6TUQD666.js.map +1 -0
- package/dist/chunk-BKXXTWIS.js +119 -0
- package/dist/chunk-BKXXTWIS.js.map +1 -0
- package/dist/chunk-D66U3PVB.js +529 -0
- package/dist/chunk-D66U3PVB.js.map +1 -0
- package/dist/chunk-HPYZ3JDX.js +206 -0
- package/dist/chunk-HPYZ3JDX.js.map +1 -0
- package/dist/chunk-KRKZGAJ3.js +769 -0
- package/dist/chunk-KRKZGAJ3.js.map +1 -0
- package/dist/chunk-SUXQTT3X.js +1268 -0
- package/dist/chunk-SUXQTT3X.js.map +1 -0
- package/dist/chunk-TW5KJREH.js +190 -0
- package/dist/chunk-TW5KJREH.js.map +1 -0
- package/dist/chunk-VQWQ5TOM.js +113 -0
- package/dist/chunk-VQWQ5TOM.js.map +1 -0
- package/dist/chunk-X4M7YWQA.js +270 -0
- package/dist/chunk-X4M7YWQA.js.map +1 -0
- package/dist/chunk-ZSLWPKXI.js +1144 -0
- package/dist/chunk-ZSLWPKXI.js.map +1 -0
- package/dist/cli.js +8 -4775
- package/dist/cli.js.map +1 -1
- package/dist/fixtures/crm-server.js +6 -1272
- package/dist/fixtures/crm-server.js.map +1 -1
- package/dist/fixtures/demo-agent.js +4 -115
- package/dist/fixtures/demo-agent.js.map +1 -1
- package/dist/index.d.ts +69 -10
- package/dist/index.js +245 -5138
- package/dist/index.js.map +1 -1
- package/dist/init-CWROGV5I.js +15 -0
- package/dist/init-CWROGV5I.js.map +1 -0
- package/dist/proxy-3Z5YEZ4R.js +154 -0
- package/dist/proxy-3Z5YEZ4R.js.map +1 -0
- package/dist/tools-3LLDG3XQ.js +15 -0
- package/dist/tools-3LLDG3XQ.js.map +1 -0
- package/llms.txt +4 -0
- package/package.json +9 -3
- package/server.json +2 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
initCommand,
|
|
3
|
+
renderStarterPolicy
|
|
4
|
+
} from "./chunk-X4M7YWQA.js";
|
|
5
|
+
import "./chunk-VQWQ5TOM.js";
|
|
6
|
+
import "./chunk-D66U3PVB.js";
|
|
7
|
+
import "./chunk-ZSLWPKXI.js";
|
|
8
|
+
import "./chunk-TW5KJREH.js";
|
|
9
|
+
import "./chunk-SUXQTT3X.js";
|
|
10
|
+
import "./chunk-5WRI5ZAA.js";
|
|
11
|
+
export {
|
|
12
|
+
initCommand,
|
|
13
|
+
renderStarterPolicy
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=init-CWROGV5I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
INIT_COMMAND,
|
|
3
|
+
createDownstreamServer,
|
|
4
|
+
startHttpProxy
|
|
5
|
+
} from "./chunk-KRKZGAJ3.js";
|
|
6
|
+
import {
|
|
7
|
+
ProxyRuntime
|
|
8
|
+
} from "./chunk-D66U3PVB.js";
|
|
9
|
+
import {
|
|
10
|
+
serveStdio
|
|
11
|
+
} from "./chunk-ZSLWPKXI.js";
|
|
12
|
+
import {
|
|
13
|
+
createFileGuard,
|
|
14
|
+
flagBool,
|
|
15
|
+
flagNumber,
|
|
16
|
+
flagString,
|
|
17
|
+
loadPolicyFor,
|
|
18
|
+
policyPathFrom
|
|
19
|
+
} from "./chunk-SUXQTT3X.js";
|
|
20
|
+
import "./chunk-5WRI5ZAA.js";
|
|
21
|
+
|
|
22
|
+
// src/commands/proxy.ts
|
|
23
|
+
import { existsSync } from "fs";
|
|
24
|
+
import { dirname } from "path";
|
|
25
|
+
import { Guard, defaultPolicy, resolveAgent } from "@agentwares/agentguard-core";
|
|
26
|
+
import { FileKillSwitch, resolvePath } from "@agentwares/agentguard-core/node";
|
|
27
|
+
function newRunId(now = /* @__PURE__ */ new Date()) {
|
|
28
|
+
return `run_${now.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14)}_${Math.random().toString(36).slice(2, 6)}`;
|
|
29
|
+
}
|
|
30
|
+
function unconfiguredPolicy(args, io) {
|
|
31
|
+
if (flagString(args, "config") !== void 0 || io.env.AGENTGUARD_CONFIG) return void 0;
|
|
32
|
+
const path = policyPathFrom(args, io);
|
|
33
|
+
if (existsSync(path)) return void 0;
|
|
34
|
+
const policy = defaultPolicy();
|
|
35
|
+
const baseDir = dirname(path);
|
|
36
|
+
return {
|
|
37
|
+
policy,
|
|
38
|
+
path,
|
|
39
|
+
baseDir,
|
|
40
|
+
stateDir: resolvePath(policy.state.dir, baseDir),
|
|
41
|
+
auditPath: resolvePath(policy.audit.path, baseDir),
|
|
42
|
+
killPath: resolvePath(policy.kill.file, baseDir)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function serveOverStdio(runtime) {
|
|
46
|
+
const server = createDownstreamServer(runtime);
|
|
47
|
+
const stop = async () => {
|
|
48
|
+
await runtime.close();
|
|
49
|
+
};
|
|
50
|
+
process.once("SIGINT", () => void stop().then(() => process.exit(0)));
|
|
51
|
+
process.once("SIGTERM", () => void stop().then(() => process.exit(0)));
|
|
52
|
+
await serveStdio(server);
|
|
53
|
+
await stop();
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
async function proxyCommand(args, io) {
|
|
57
|
+
const log = (line) => io.err(`[agentguard] ${line}`);
|
|
58
|
+
const modeOverride = flagString(args, "mode");
|
|
59
|
+
const http = flagBool(args, "http") === true;
|
|
60
|
+
const unconfigured = http ? void 0 : unconfiguredPolicy(args, io);
|
|
61
|
+
if (unconfigured) {
|
|
62
|
+
if (modeOverride === "dry-run" || modeOverride === "enforce")
|
|
63
|
+
unconfigured.policy.mode = modeOverride;
|
|
64
|
+
const runtime2 = new ProxyRuntime({
|
|
65
|
+
loaded: unconfigured,
|
|
66
|
+
guard: new Guard({
|
|
67
|
+
policy: unconfigured.policy,
|
|
68
|
+
env: io.env,
|
|
69
|
+
kill: new FileKillSwitch(unconfigured.killPath)
|
|
70
|
+
}),
|
|
71
|
+
configured: false,
|
|
72
|
+
defaultRunId: flagString(args, "run-id") ?? newRunId(),
|
|
73
|
+
log
|
|
74
|
+
});
|
|
75
|
+
await runtime2.start();
|
|
76
|
+
log(
|
|
77
|
+
`no policy file at ${unconfigured.path}: serving agentguard's own read-only tools only. To guard your MCP servers, run \`${INIT_COMMAND}\` in the project directory.`
|
|
78
|
+
);
|
|
79
|
+
return serveOverStdio(runtime2);
|
|
80
|
+
}
|
|
81
|
+
const loaded = loadPolicyFor(args, io);
|
|
82
|
+
if (modeOverride === "dry-run" || modeOverride === "enforce") loaded.policy.mode = modeOverride;
|
|
83
|
+
const agentName = flagString(args, "agent");
|
|
84
|
+
let agent = void 0;
|
|
85
|
+
if (agentName) {
|
|
86
|
+
const resolved = await resolveAgent(loaded.policy, { name: agentName });
|
|
87
|
+
if (resolved.error) {
|
|
88
|
+
io.err(
|
|
89
|
+
`unknown agent "${agentName}" \u2014 agents in agentguard.yaml: ${loaded.policy.agents.map((a) => a.name).join(", ") || "none"}`
|
|
90
|
+
);
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
agent = resolved.agent;
|
|
94
|
+
}
|
|
95
|
+
let approvalBase;
|
|
96
|
+
const fileGuard = createFileGuard(loaded, {
|
|
97
|
+
log,
|
|
98
|
+
env: io.env,
|
|
99
|
+
approvalUrl: (r) => approvalBase ? `${approvalBase.baseUrl}/approve/${r.id}?token=${approvalBase.token}` : void 0,
|
|
100
|
+
onEvent: (e) => {
|
|
101
|
+
if (e.type === "APPROVAL_DECIDED") return;
|
|
102
|
+
log(`${e.type} ${e.tool} (run ${e.runId})${e.error ? `: ${e.error.cause}` : ""}`);
|
|
103
|
+
if (e.type === "APPROVAL_REQUIRED" && e.approval)
|
|
104
|
+
log(`approve with: agentguard approve ${e.approval.id}`);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const runtime = new ProxyRuntime({
|
|
108
|
+
loaded,
|
|
109
|
+
guard: fileGuard.guard,
|
|
110
|
+
agent,
|
|
111
|
+
defaultRunId: flagString(args, "run-id") ?? newRunId(),
|
|
112
|
+
log
|
|
113
|
+
});
|
|
114
|
+
await runtime.start();
|
|
115
|
+
const killed = await fileGuard.kill.check();
|
|
116
|
+
if (killed.killed)
|
|
117
|
+
log(
|
|
118
|
+
`kill switch is ON (${killed.reason}); every call returns KILLED until \`agentguard resume\``
|
|
119
|
+
);
|
|
120
|
+
if (runtime.upstreamStatus().length === 0)
|
|
121
|
+
log(
|
|
122
|
+
`${loaded.path} lists no upstreams: serving agentguard's own read-only tools only. Add servers under \`upstreams:\` to guard them.`
|
|
123
|
+
);
|
|
124
|
+
if (http) {
|
|
125
|
+
const server = await startHttpProxy({
|
|
126
|
+
runtime,
|
|
127
|
+
port: flagNumber(args, "port") ?? 8788,
|
|
128
|
+
host: flagString(args, "host") ?? "127.0.0.1",
|
|
129
|
+
token: io.env.AGENTGUARD_HTTP_TOKEN
|
|
130
|
+
});
|
|
131
|
+
approvalBase = { baseUrl: server.url.replace(/\/mcp$/, ""), token: server.token };
|
|
132
|
+
log(
|
|
133
|
+
`Streamable HTTP at ${server.url} \xB7 GET ${approvalBase.baseUrl}/health \xB7 control token in ${loaded.stateDir}/http.json`
|
|
134
|
+
);
|
|
135
|
+
log(
|
|
136
|
+
`point your agent at ${server.url} (send X-Run-Id per run; Authorization: Bearer <agent key> for scoped agents)`
|
|
137
|
+
);
|
|
138
|
+
const stop = async () => {
|
|
139
|
+
await server.close();
|
|
140
|
+
await runtime.close();
|
|
141
|
+
process.exit(0);
|
|
142
|
+
};
|
|
143
|
+
process.once("SIGINT", () => void stop());
|
|
144
|
+
process.once("SIGTERM", () => void stop());
|
|
145
|
+
await new Promise(() => void 0);
|
|
146
|
+
}
|
|
147
|
+
return serveOverStdio(runtime);
|
|
148
|
+
}
|
|
149
|
+
export {
|
|
150
|
+
newRunId,
|
|
151
|
+
proxyCommand,
|
|
152
|
+
unconfiguredPolicy
|
|
153
|
+
};
|
|
154
|
+
//# sourceMappingURL=proxy-3Z5YEZ4R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/proxy.ts"],"sourcesContent":["/**\n * `agentguard proxy` — stdio by default (what MCP clients spawn), `--http` for Streamable HTTP\n * with the control endpoints. Logs go to stderr only; stdout is the MCP channel.\n */\nimport { existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { serveStdio } from \"@agentwares/mcp-kit\";\nimport { Guard, defaultPolicy, resolveAgent } from \"@agentwares/agentguard-core\";\nimport { FileKillSwitch, resolvePath, type LoadedPolicy } from \"@agentwares/agentguard-core/node\";\nimport { flagBool, flagNumber, flagString, type ParsedArgs } from \"../args.js\";\nimport { createFileGuard, loadPolicyFor, policyPathFrom, type Io } from \"../context.js\";\nimport { startHttpProxy } from \"../proxy/http.js\";\nimport { INIT_COMMAND } from \"../proxy/own-tools.js\";\nimport { ProxyRuntime } from \"../proxy/runtime.js\";\nimport { createDownstreamServer } from \"../proxy/server.js\";\n\nexport function newRunId(now: Date = new Date()): string {\n return `run_${now\n .toISOString()\n .replace(/[-:.TZ]/g, \"\")\n .slice(0, 14)}_${Math.random().toString(36).slice(2, 6)}`;\n}\n\n/**\n * The policy agentguard runs on when no `agentguard.yaml` exists and none was named: the\n * defaults, no upstreams, paths resolved where the file would be. It is what an install button\n * or a registry install starts before `init` has run. Nothing is written for it: the guard built\n * on it keeps counters, audit and approvals in memory, so the proxy leaves no `.agentguard/` in\n * whatever directory the client spawned it in.\n *\n * `undefined` when a policy file exists, or when one was named with `--config` or\n * `AGENTGUARD_CONFIG` — a named file that is missing is still an error.\n */\nexport function unconfiguredPolicy(args: ParsedArgs, io: Io): LoadedPolicy | undefined {\n if (flagString(args, \"config\") !== undefined || io.env.AGENTGUARD_CONFIG) return undefined;\n const path = policyPathFrom(args, io);\n if (existsSync(path)) return undefined;\n const policy = defaultPolicy();\n const baseDir = dirname(path);\n return {\n policy,\n path,\n baseDir,\n stateDir: resolvePath(policy.state.dir, baseDir),\n auditPath: resolvePath(policy.audit.path, baseDir),\n killPath: resolvePath(policy.kill.file, baseDir),\n };\n}\n\nasync function serveOverStdio(runtime: ProxyRuntime): Promise<number> {\n const server = createDownstreamServer(runtime);\n const stop = async (): Promise<void> => {\n await runtime.close();\n };\n process.once(\"SIGINT\", () => void stop().then(() => process.exit(0)));\n process.once(\"SIGTERM\", () => void stop().then(() => process.exit(0)));\n await serveStdio(server);\n await stop();\n return 0;\n}\n\nexport async function proxyCommand(args: ParsedArgs, io: Io): Promise<number> {\n const log = (line: string): void => io.err(`[agentguard] ${line}`);\n const modeOverride = flagString(args, \"mode\");\n const http = flagBool(args, \"http\") === true;\n\n // No policy file and none named: serve agentguard's own read-only tools over stdio rather than\n // exit, so a client that installed it from a button or a registry gets a working server that\n // says how to set it up. `--http` still needs a policy (it writes its control token beside it).\n const unconfigured = http ? undefined : unconfiguredPolicy(args, io);\n if (unconfigured) {\n if (modeOverride === \"dry-run\" || modeOverride === \"enforce\")\n unconfigured.policy.mode = modeOverride;\n const runtime = new ProxyRuntime({\n loaded: unconfigured,\n guard: new Guard({\n policy: unconfigured.policy,\n env: io.env,\n kill: new FileKillSwitch(unconfigured.killPath),\n }),\n configured: false,\n defaultRunId: flagString(args, \"run-id\") ?? newRunId(),\n log,\n });\n await runtime.start();\n log(\n `no policy file at ${unconfigured.path}: serving agentguard's own read-only tools only. To guard your MCP servers, run \\`${INIT_COMMAND}\\` in the project directory.`,\n );\n return serveOverStdio(runtime);\n }\n\n const loaded = loadPolicyFor(args, io);\n if (modeOverride === \"dry-run\" || modeOverride === \"enforce\") loaded.policy.mode = modeOverride;\n\n const agentName = flagString(args, \"agent\");\n let agent = undefined;\n if (agentName) {\n const resolved = await resolveAgent(loaded.policy, { name: agentName });\n if (resolved.error) {\n io.err(\n `unknown agent \"${agentName}\" — agents in agentguard.yaml: ${loaded.policy.agents.map((a) => a.name).join(\", \") || \"none\"}`,\n );\n return 1;\n }\n agent = resolved.agent;\n }\n\n let approvalBase: { baseUrl: string; token: string } | undefined;\n const fileGuard = createFileGuard(loaded, {\n log,\n env: io.env,\n approvalUrl: (r) =>\n approvalBase\n ? `${approvalBase.baseUrl}/approve/${r.id}?token=${approvalBase.token}`\n : undefined,\n onEvent: (e) => {\n if (e.type === \"APPROVAL_DECIDED\") return;\n log(`${e.type} ${e.tool} (run ${e.runId})${e.error ? `: ${e.error.cause}` : \"\"}`);\n if (e.type === \"APPROVAL_REQUIRED\" && e.approval)\n log(`approve with: agentguard approve ${e.approval.id}`);\n },\n });\n const runtime = new ProxyRuntime({\n loaded,\n guard: fileGuard.guard,\n agent,\n defaultRunId: flagString(args, \"run-id\") ?? newRunId(),\n log,\n });\n await runtime.start();\n const killed = await fileGuard.kill.check();\n if (killed.killed)\n log(\n `kill switch is ON (${killed.reason}); every call returns KILLED until \\`agentguard resume\\``,\n );\n if (runtime.upstreamStatus().length === 0)\n log(\n `${loaded.path} lists no upstreams: serving agentguard's own read-only tools only. Add servers under \\`upstreams:\\` to guard them.`,\n );\n\n if (http) {\n const server = await startHttpProxy({\n runtime,\n port: flagNumber(args, \"port\") ?? 8788,\n host: flagString(args, \"host\") ?? \"127.0.0.1\",\n token: io.env.AGENTGUARD_HTTP_TOKEN,\n });\n approvalBase = { baseUrl: server.url.replace(/\\/mcp$/, \"\"), token: server.token };\n log(\n `Streamable HTTP at ${server.url} · GET ${approvalBase.baseUrl}/health · control token in ${loaded.stateDir}/http.json`,\n );\n log(\n `point your agent at ${server.url} (send X-Run-Id per run; Authorization: Bearer <agent key> for scoped agents)`,\n );\n const stop = async (): Promise<void> => {\n await server.close();\n await runtime.close();\n process.exit(0);\n };\n process.once(\"SIGINT\", () => void stop());\n process.once(\"SIGTERM\", () => void stop());\n await new Promise<never>(() => undefined);\n }\n\n return serveOverStdio(runtime);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAIA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AAExB,SAAS,OAAO,eAAe,oBAAoB;AACnD,SAAS,gBAAgB,mBAAsC;AAQxD,SAAS,SAAS,MAAY,oBAAI,KAAK,GAAW;AACvD,SAAO,OAAO,IACX,YAAY,EACZ,QAAQ,YAAY,EAAE,EACtB,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC3D;AAYO,SAAS,mBAAmB,MAAkB,IAAkC;AACrF,MAAI,WAAW,MAAM,QAAQ,MAAM,UAAa,GAAG,IAAI,kBAAmB,QAAO;AACjF,QAAM,OAAO,eAAe,MAAM,EAAE;AACpC,MAAI,WAAW,IAAI,EAAG,QAAO;AAC7B,QAAM,SAAS,cAAc;AAC7B,QAAM,UAAU,QAAQ,IAAI;AAC5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,YAAY,OAAO,MAAM,KAAK,OAAO;AAAA,IAC/C,WAAW,YAAY,OAAO,MAAM,MAAM,OAAO;AAAA,IACjD,UAAU,YAAY,OAAO,KAAK,MAAM,OAAO;AAAA,EACjD;AACF;AAEA,eAAe,eAAe,SAAwC;AACpE,QAAM,SAAS,uBAAuB,OAAO;AAC7C,QAAM,OAAO,YAA2B;AACtC,UAAM,QAAQ,MAAM;AAAA,EACtB;AACA,UAAQ,KAAK,UAAU,MAAM,KAAK,KAAK,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC;AACpE,UAAQ,KAAK,WAAW,MAAM,KAAK,KAAK,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC;AACrE,QAAM,WAAW,MAAM;AACvB,QAAM,KAAK;AACX,SAAO;AACT;AAEA,eAAsB,aAAa,MAAkB,IAAyB;AAC5E,QAAM,MAAM,CAAC,SAAuB,GAAG,IAAI,gBAAgB,IAAI,EAAE;AACjE,QAAM,eAAe,WAAW,MAAM,MAAM;AAC5C,QAAM,OAAO,SAAS,MAAM,MAAM,MAAM;AAKxC,QAAM,eAAe,OAAO,SAAY,mBAAmB,MAAM,EAAE;AACnE,MAAI,cAAc;AAChB,QAAI,iBAAiB,aAAa,iBAAiB;AACjD,mBAAa,OAAO,OAAO;AAC7B,UAAMA,WAAU,IAAI,aAAa;AAAA,MAC/B,QAAQ;AAAA,MACR,OAAO,IAAI,MAAM;AAAA,QACf,QAAQ,aAAa;AAAA,QACrB,KAAK,GAAG;AAAA,QACR,MAAM,IAAI,eAAe,aAAa,QAAQ;AAAA,MAChD,CAAC;AAAA,MACD,YAAY;AAAA,MACZ,cAAc,WAAW,MAAM,QAAQ,KAAK,SAAS;AAAA,MACrD;AAAA,IACF,CAAC;AACD,UAAMA,SAAQ,MAAM;AACpB;AAAA,MACE,qBAAqB,aAAa,IAAI,qFAAqF,YAAY;AAAA,IACzI;AACA,WAAO,eAAeA,QAAO;AAAA,EAC/B;AAEA,QAAM,SAAS,cAAc,MAAM,EAAE;AACrC,MAAI,iBAAiB,aAAa,iBAAiB,UAAW,QAAO,OAAO,OAAO;AAEnF,QAAM,YAAY,WAAW,MAAM,OAAO;AAC1C,MAAI,QAAQ;AACZ,MAAI,WAAW;AACb,UAAM,WAAW,MAAM,aAAa,OAAO,QAAQ,EAAE,MAAM,UAAU,CAAC;AACtE,QAAI,SAAS,OAAO;AAClB,SAAG;AAAA,QACD,kBAAkB,SAAS,uCAAkC,OAAO,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,MAAM;AAAA,MAC3H;AACA,aAAO;AAAA,IACT;AACA,YAAQ,SAAS;AAAA,EACnB;AAEA,MAAI;AACJ,QAAM,YAAY,gBAAgB,QAAQ;AAAA,IACxC;AAAA,IACA,KAAK,GAAG;AAAA,IACR,aAAa,CAAC,MACZ,eACI,GAAG,aAAa,OAAO,YAAY,EAAE,EAAE,UAAU,aAAa,KAAK,KACnE;AAAA,IACN,SAAS,CAAC,MAAM;AACd,UAAI,EAAE,SAAS,mBAAoB;AACnC,UAAI,GAAG,EAAE,IAAI,IAAI,EAAE,IAAI,SAAS,EAAE,KAAK,IAAI,EAAE,QAAQ,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,EAAE;AAChF,UAAI,EAAE,SAAS,uBAAuB,EAAE;AACtC,YAAI,oCAAoC,EAAE,SAAS,EAAE,EAAE;AAAA,IAC3D;AAAA,EACF,CAAC;AACD,QAAM,UAAU,IAAI,aAAa;AAAA,IAC/B;AAAA,IACA,OAAO,UAAU;AAAA,IACjB;AAAA,IACA,cAAc,WAAW,MAAM,QAAQ,KAAK,SAAS;AAAA,IACrD;AAAA,EACF,CAAC;AACD,QAAM,QAAQ,MAAM;AACpB,QAAM,SAAS,MAAM,UAAU,KAAK,MAAM;AAC1C,MAAI,OAAO;AACT;AAAA,MACE,sBAAsB,OAAO,MAAM;AAAA,IACrC;AACF,MAAI,QAAQ,eAAe,EAAE,WAAW;AACtC;AAAA,MACE,GAAG,OAAO,IAAI;AAAA,IAChB;AAEF,MAAI,MAAM;AACR,UAAM,SAAS,MAAM,eAAe;AAAA,MAClC;AAAA,MACA,MAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAClC,MAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAClC,OAAO,GAAG,IAAI;AAAA,IAChB,CAAC;AACD,mBAAe,EAAE,SAAS,OAAO,IAAI,QAAQ,UAAU,EAAE,GAAG,OAAO,OAAO,MAAM;AAChF;AAAA,MACE,sBAAsB,OAAO,GAAG,aAAU,aAAa,OAAO,iCAA8B,OAAO,QAAQ;AAAA,IAC7G;AACA;AAAA,MACE,uBAAuB,OAAO,GAAG;AAAA,IACnC;AACA,UAAM,OAAO,YAA2B;AACtC,YAAM,OAAO,MAAM;AACnB,YAAM,QAAQ,MAAM;AACpB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,YAAQ,KAAK,UAAU,MAAM,KAAK,KAAK,CAAC;AACxC,YAAQ,KAAK,WAAW,MAAM,KAAK,KAAK,CAAC;AACzC,UAAM,IAAI,QAAe,MAAM,MAAS;AAAA,EAC1C;AAEA,SAAO,eAAe,OAAO;AAC/B;","names":["runtime"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatToolTable,
|
|
3
|
+
probeUpstreams,
|
|
4
|
+
toolsCommand
|
|
5
|
+
} from "./chunk-VQWQ5TOM.js";
|
|
6
|
+
import "./chunk-D66U3PVB.js";
|
|
7
|
+
import "./chunk-ZSLWPKXI.js";
|
|
8
|
+
import "./chunk-SUXQTT3X.js";
|
|
9
|
+
import "./chunk-5WRI5ZAA.js";
|
|
10
|
+
export {
|
|
11
|
+
formatToolTable,
|
|
12
|
+
probeUpstreams,
|
|
13
|
+
toolsCommand
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=tools-3LLDG3XQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/llms.txt
CHANGED
|
@@ -6,6 +6,10 @@ Set up: `npx -y @agentwares/agentguard init` in the project directory writes age
|
|
|
6
6
|
|
|
7
7
|
Started with no agentguard.yaml (an editor install button, a registry install, the repo's Dockerfile), the proxy fronts no servers and serves three read-only tools of its own: `agentguard_get_status` (what it guards, caps used and remaining, kill switch, pending approvals), `agentguard_get_report` (what a run did, or would have done in dry-run) and `agentguard_verify_audit_log` (the hash chain). With upstreams configured, the agent sees only the upstreams' tools.
|
|
8
8
|
|
|
9
|
+
Hook mode: `npx -y @agentwares/agentguard hooks install` (add `--client codex`, `--client gemini` or `--client all`) writes a pre-execution hook (Claude Code PreToolUse, Codex PreToolUse, Gemini CLI BeforeTool) that checks the coding agent's own shell commands, file edits and MCP calls against the same agentguard.yaml. Irreversible commands (git push, merges, tag deletion, rm outside the workspace, package publish, sending mail or messages, edits to the guard itself) run only on a recent turn a person typed that names the action; in Claude Code that is read from the session transcript, and text the model writes never counts. Otherwise the agent gets APPROVAL_REQUIRED with an id, and `agentguard approve <id>` lets the identical command run once. Dry-run (log only) until `hooks.mode: enforce`.
|
|
10
|
+
|
|
11
|
+
Audit: `npx -y @agentwares/agentguard audit [--since 7d|30d|all] [--json]` reads the repository's CLAUDE.md, AGENTS.md, GEMINI.md and .cursor/rules (and `audit.rules` in agentguard.yaml) and this machine's Claude Code and Codex sessions in it, and reports per rule how many sessions broke it and when. Rules are recognised by a pattern library with no LLM (never push to main, never force-push, never --no-verify, run X before pushing, use pnpm not npm, do not edit or commit a path, no new dependencies without asking, never rm outside the repo, never publish, never deploy, never run a named command), or stated with an inline `<!-- agentguard: <check> -->`. It runs locally and sends nothing; `--json` carries counts, rule ids and dates only. `--enforce` writes the checkable rules into agentguard.yaml as hook-mode rules in dry-run and installs the hook. The plugin's `/agentguard:audit` has your own agent judge the rules no script can check.
|
|
12
|
+
|
|
9
13
|
## Links
|
|
10
14
|
|
|
11
15
|
- [README (install in 60 seconds)](https://github.com/agentwares/agentguard/tree/main/apps/agentguard-cli#readme)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentwares/agentguard",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "MCP policy proxy for AI agents: hard spend limits, destructive-action gating with approvals, a kill switch, scoped credentials, dry-run writes with mutation diffs, loop breaker, blast-radius caps and a hash-chained audit log. No LLM calls, no phone-home, no account.",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "MCP policy proxy for AI agents: hard spend limits, destructive-action gating with approvals, a kill switch, scoped credentials, dry-run writes with mutation diffs, loop breaker, blast-radius caps and a hash-chained audit log. Hook mode applies the same policy to Claude Code, Codex and Gemini CLI shell commands and file edits, and runs irreversible commands only on a turn a person typed. Audit mode reports which CLAUDE.md / AGENTS.md rules your coding agents broke, from your own sessions, locally. No LLM calls, no phone-home, no account.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -43,6 +43,12 @@
|
|
|
43
43
|
"dry-run",
|
|
44
44
|
"audit-log",
|
|
45
45
|
"claude-code",
|
|
46
|
+
"claude-code-hooks",
|
|
47
|
+
"claude-md",
|
|
48
|
+
"agents-md",
|
|
49
|
+
"codex",
|
|
50
|
+
"gemini-cli",
|
|
51
|
+
"coding-agents",
|
|
46
52
|
"cursor",
|
|
47
53
|
"guardrails",
|
|
48
54
|
"mcp-server",
|
|
@@ -62,7 +68,7 @@
|
|
|
62
68
|
"conformance": "node scripts/conformance.mjs"
|
|
63
69
|
},
|
|
64
70
|
"dependencies": {
|
|
65
|
-
"@agentwares/agentguard-core": "^0.1.
|
|
71
|
+
"@agentwares/agentguard-core": "^0.1.5",
|
|
66
72
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
67
73
|
"yaml": "^2.9.0",
|
|
68
74
|
"zod": "^4.5.4"
|
package/server.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.agentwares/agentguard",
|
|
4
4
|
"description": "MCP policy proxy: spend caps, approvals for destructive tools, kill switch, dry-run, audit log.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.9",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/agentwares/agentguard",
|
|
8
8
|
"source": "github",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"registryType": "npm",
|
|
16
16
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
17
17
|
"identifier": "@agentwares/agentguard",
|
|
18
|
-
"version": "0.1.
|
|
18
|
+
"version": "0.1.9",
|
|
19
19
|
"runtimeHint": "npx",
|
|
20
20
|
"transport": {
|
|
21
21
|
"type": "stdio"
|