{"_id":"@agentwares/agentguard","_rev":"6-3874000be0e6366aed12fe246463db9a","name":"@agentwares/agentguard","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"@agentwares/agentguard","version":"0.1.0","keywords":["mcp","mcp-proxy","model-context-protocol","ai-agents","agent-safety","spend-limit","kill-switch","dry-run","audit-log","claude-code","cursor","guardrails"],"license":"MIT","_id":"@agentwares/agentguard@0.1.0","maintainers":[{"name":"umerbukhari","email":"umer.bukhari@gmail.com"}],"homepage":"https://github.com/agentwares/agentwares/tree/main/apps/agentguard-cli#readme","bugs":{"url":"https://github.com/agentwares/agentwares/issues"},"bin":{"agentguard":"dist/cli.js"},"dist":{"shasum":"35ac0225ab1c8d053eb4d6f91fd1b518eff4a69b","tarball":"https://registry.npmjs.org/@agentwares/agentguard/-/agentguard-0.1.0.tgz","fileCount":13,"integrity":"sha512-Zcu73ZpLyALqWuFARMQRSmGW0x0aOtBO06zRjhhLUyNVRBe4lBVS823Jjd1ZdDV+XluP90j+NryJU1r0pg1G0w==","signatures":[{"sig":"MEYCIQCayPgP95VXIFHxIOaqJjbXlBN8EQsM5bRHGhGdG/OlegIhAKgR+3eMbOMXUqwMpWrIq6mSS6+jI4IkhoOImtzluWDD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1428197},"main":"./dist/index.js","type":"module","_from":"file:agentwares-agentguard-0.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"mcpName":"io.github.agentwares/agentguard","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","listing":"node scripts/generate-listing.mjs","typecheck":"tsc --noEmit","conformance":"node scripts/conformance.mjs"},"_npmUser":{"name":"umerbukhari","email":"umer.bukhari@gmail.com"},"_resolved":"/private/var/folders/2p/2j2wcvfs4wz6v0nfr4h455k40000gn/T/d67e160637e9975bde4bda104f0aa911/agentwares-agentguard-0.1.0.tgz","_integrity":"sha512-Zcu73ZpLyALqWuFARMQRSmGW0x0aOtBO06zRjhhLUyNVRBe4lBVS823Jjd1ZdDV+XluP90j+NryJU1r0pg1G0w==","repository":{"url":"git+https://github.com/agentwares/agentwares.git","type":"git","directory":"apps/agentguard-cli"},"_npmVersion":"10.9.8","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, ","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","yaml":"^2.9.0","@modelcontextprotocol/sdk":"^1.30.0","@agentwares/agentguard-core":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","@agentwares/notify":"^0.1.0","@agentwares/mcp-kit":"^0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/agentguard_0.1.0_1788483425926_0.0987306635513685","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@agentwares/agentguard","version":"0.1.1","keywords":["mcp","mcp-proxy","model-context-protocol","ai-agents","agent-safety","spend-limit","kill-switch","dry-run","audit-log","claude-code","cursor","guardrails"],"license":"MIT","_id":"@agentwares/agentguard@0.1.1","maintainers":[{"name":"umerbukhari","email":"umer.bukhari@gmail.com"}],"homepage":"https://github.com/agentwares/agentguard#readme","bugs":{"url":"https://github.com/agentwares/agentguard/issues"},"bin":{"agentguard":"dist/cli.js"},"dist":{"shasum":"386a8470c9521fa9cea8c50714beea310127f1dd","tarball":"https://registry.npmjs.org/@agentwares/agentguard/-/agentguard-0.1.1.tgz","fileCount":13,"integrity":"sha512-Y2Q4FZPtBNUREsbiNIuWAv5Fz0C3VIF3dLT9LpRAAFQ/jtKGRo4+fOVoiia/6pmJ28+2+eRQYQg2T1/kd365dg==","signatures":[{"sig":"MEQCIEM/JuaLWCsxAwODVrfDMygczwsAATlLbWEF/4RXeb2+AiA8HCFlxEeMT+6I+dImqwniF9Bp2wmVII6fnIU7+j1F8Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCID0fBt055osgdRAjl1P0xHZkP4pI6U9EiQt0usUx0bdCAiAzCRyuDwjtyspTCVGkG0JKILnp0WBaDJM9e8Geaw+Iyg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1428241},"main":"./dist/index.js","type":"module","_from":"file:agentwares-agentguard-0.1.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"mcpName":"io.github.agentwares/agentguard","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","listing":"node scripts/generate-listing.mjs","typecheck":"tsc --noEmit","conformance":"node scripts/conformance.mjs"},"_npmUser":{"name":"umerbukhari","email":"umer.bukhari@gmail.com"},"_resolved":"/private/var/folders/2p/2j2wcvfs4wz6v0nfr4h455k40000gn/T/a581f7be3e92040e1904eca3080774a6/agentwares-agentguard-0.1.1.tgz","_integrity":"sha512-Y2Q4FZPtBNUREsbiNIuWAv5Fz0C3VIF3dLT9LpRAAFQ/jtKGRo4+fOVoiia/6pmJ28+2+eRQYQg2T1/kd365dg==","repository":{"url":"git+https://github.com/agentwares/agentguard.git","type":"git","directory":"apps/agentguard-cli"},"_npmVersion":"10.9.8","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, ","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","yaml":"^2.9.0","@modelcontextprotocol/sdk":"^1.30.0","@agentwares/agentguard-core":"^0.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","@agentwares/notify":"^0.1.0","@agentwares/mcp-kit":"^0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/agentguard_0.1.1_1788807029015_0.4429177260491395","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@agentwares/agentguard","version":"0.1.2","keywords":["mcp","mcp-proxy","model-context-protocol","ai-agents","agent-safety","spend-limit","kill-switch","dry-run","audit-log","claude-code","cursor","guardrails"],"license":"MIT","_id":"@agentwares/agentguard@0.1.2","maintainers":[{"name":"umerbukhari","email":"umer.bukhari@gmail.com"}],"homepage":"https://github.com/agentwares/agentguard#readme","bugs":{"url":"https://github.com/agentwares/agentguard/issues"},"bin":{"agentguard":"dist/cli.js"},"dist":{"shasum":"61f6077b510d8471ce49f2f61e47bc424a9c0ccd","tarball":"https://registry.npmjs.org/@agentwares/agentguard/-/agentguard-0.1.2.tgz","fileCount":13,"integrity":"sha512-z9arHOxdM7lkfWPFVjWtroak2IQC+awD8l8n8i9SG6dOQDRW84fNXpCVmhb5vGHsYx7R1FXvUXXrlvR1B0N2+Q==","signatures":[{"sig":"MEQCIGCoo5XGBYFok0u3ms5JA+n0IJbVXondlvlO2nCquB+DAiAoWWG3z2BklEKRTPQIWyisgZA9TBr9e3f8AWixauTSDw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDgcnQn9NmHT75i9/01mnilEaxWLLP+Eo+eoGhLfyl/MAiAZRInon7us2gsEtbBRStVK+924yYSzCpwzNxksJHbd1Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1428831},"main":"./dist/index.js","type":"module","_from":"file:agentwares-agentguard-0.1.2.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"mcpName":"io.github.agentwares/agentguard","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","listing":"node scripts/generate-listing.mjs","typecheck":"tsc --noEmit","conformance":"node scripts/conformance.mjs"},"_npmUser":{"name":"umerbukhari","email":"umer.bukhari@gmail.com"},"_resolved":"/private/var/folders/2p/2j2wcvfs4wz6v0nfr4h455k40000gn/T/bd1d41021b797e518ff1beb23ff62509/agentwares-agentguard-0.1.2.tgz","_integrity":"sha512-z9arHOxdM7lkfWPFVjWtroak2IQC+awD8l8n8i9SG6dOQDRW84fNXpCVmhb5vGHsYx7R1FXvUXXrlvR1B0N2+Q==","repository":{"url":"git+https://github.com/agentwares/agentguard.git","type":"git","directory":"apps/agentguard-cli"},"_npmVersion":"10.9.8","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, ","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","yaml":"^2.9.0","@modelcontextprotocol/sdk":"^1.30.0","@agentwares/agentguard-core":"^0.1.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","@agentwares/notify":"^0.1.0","@agentwares/mcp-kit":"^0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/agentguard_0.1.2_1788807265839_0.9591822714229523","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@agentwares/agentguard","version":"0.1.3","keywords":["mcp","mcp-proxy","model-context-protocol","ai-agents","agent-safety","spend-limit","kill-switch","dry-run","audit-log","claude-code","cursor","guardrails"],"license":"MIT","_id":"@agentwares/agentguard@0.1.3","maintainers":[{"name":"umerbukhari","email":"umer.bukhari@gmail.com"}],"homepage":"https://github.com/agentwares/agentguard#readme","bugs":{"url":"https://github.com/agentwares/agentguard/issues"},"bin":{"agentguard":"dist/cli.js"},"dist":{"shasum":"ee4ebc994799f506c795be12ffafd48ea280cadf","tarball":"https://registry.npmjs.org/@agentwares/agentguard/-/agentguard-0.1.3.tgz","fileCount":14,"integrity":"sha512-jwmju2gl/jOXdt3P4/Kvi6u+p+4z6K8sQM3FxlkM31CoGVjvg+0aUYygHaXX7owUYfdY26PL4eeA+Zc4vHr2wQ==","signatures":[{"sig":"MEUCIQCmkzueqfnnP0WOtOcI1RQ/KLn9XTPz4CanPHYWas/sMwIgNZoLbuLNan31Fi2CNFvw7AgbPpv9OjNWebkkvdbh6zc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDhzJvaJrzXLx8eUSt+sM9F98NdyAyc6+w+ibKOJ2tlmwIge3/rXXQAkIFXX4P0C0PLC78h7piHYwS5HAoB5AnX3AA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1526694},"main":"./dist/index.js","type":"module","_from":"file:agentwares-agentguard-0.1.3.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"mcpName":"io.github.agentwares/agentguard","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","listing":"node scripts/generate-listing.mjs","typecheck":"tsc --noEmit","conformance":"node scripts/conformance.mjs"},"_npmUser":{"name":"umerbukhari","email":"umer.bukhari@gmail.com"},"_resolved":"/private/var/folders/2p/2j2wcvfs4wz6v0nfr4h455k40000gn/T/e0c33db56a5faf84d3016a76ea7d6d2d/agentwares-agentguard-0.1.3.tgz","_integrity":"sha512-jwmju2gl/jOXdt3P4/Kvi6u+p+4z6K8sQM3FxlkM31CoGVjvg+0aUYygHaXX7owUYfdY26PL4eeA+Zc4vHr2wQ==","repository":{"url":"git+https://github.com/agentwares/agentguard.git","type":"git","directory":"apps/agentguard-cli"},"_npmVersion":"10.9.8","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, ","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","yaml":"^2.9.0","@modelcontextprotocol/sdk":"^1.30.0","@agentwares/agentguard-core":"^0.1.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","@agentwares/notify":"^0.1.1","@agentwares/mcp-kit":"^0.2.0"},"_npmOperationalInternal":{"tmp":"tmp/agentguard_0.1.3_1788820580011_0.2499902405669241","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@agentwares/agentguard","version":"0.1.4","keywords":["mcp","mcp-proxy","model-context-protocol","ai-agents","agent-safety","spend-limit","kill-switch","dry-run","audit-log","claude-code","cursor","guardrails"],"license":"MIT","_id":"@agentwares/agentguard@0.1.4","maintainers":[{"name":"umerbukhari","email":"umer.bukhari@gmail.com"}],"homepage":"https://github.com/agentwares/agentguard#readme","bugs":{"url":"https://github.com/agentwares/agentguard/issues"},"bin":{"agentguard":"dist/cli.js"},"dist":{"shasum":"7078b00c03eb1d4e44cc11a1a354276626c52476","tarball":"https://registry.npmjs.org/@agentwares/agentguard/-/agentguard-0.1.4.tgz","fileCount":13,"integrity":"sha512-jD+C2uo0f2h/GYZkpJ7AWVAnTw8/6Eym/rtIv6ZT7QWBY8UeD3VsOMjcxG20jUWwUmSXyiuRB/wbMaLmmryFMQ==","signatures":[{"sig":"MEYCIQDdq7TebBQTURG7viR1VvPR+SC8+vdbzm4WXXz7tFeKxAIhAM9L0LRwaF7OKJsHkEiL+sk/F6H0nML6Eza7x4gEXRhp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCID1F0/rh2c+HuiULV9KcrQcz3hwc5smVLS3ipcdxWrA7AiBbTHNEFJpJW1qW4Vasc/ufaxFEKZ5cha5poR8uxXCFpg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1620686},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"8aa61b3c12df11c0141e00dad3a4330bc3b84abb","mcpName":"io.github.agentwares/agentguard","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","listing":"node scripts/generate-listing.mjs","typecheck":"tsc --noEmit","conformance":"node scripts/conformance.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e59feed7-a1f7-404a-8d69-891e8d9b2208"}},"repository":{"url":"git+https://github.com/agentwares/agentguard.git","type":"git","directory":"apps/agentguard-cli"},"_npmVersion":"12.0.2","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, ","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","yaml":"^2.9.0","@modelcontextprotocol/sdk":"^1.30.0","@agentwares/agentguard-core":"workspace:^"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","@agentwares/notify":"workspace:^","@agentwares/mcp-kit":"workspace:^"},"_npmOperationalInternal":{"tmp":"tmp/agentguard_0.1.4_1789148583450_0.2811628951348015","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"_id":"@agentwares/agentguard@0.1.5","bin":{"agentguard":"dist/cli.js"},"bugs":{"url":"https://github.com/agentwares/agentguard/issues"},"dist":{"shasum":"1f10dc475c2ba102ba13eafa60c3bbb23c7c5f31","tarball":"https://registry.npmjs.org/@agentwares/agentguard/-/agentguard-0.1.5.tgz","fileCount":13,"integrity":"sha512-P8B3hEWkVtob/Rqffy9an+VbgADaKHjuaDmJqJKdPNASG54Xq2kZUzlYO0AKyyOq7xhVsd9LjaCm6ryvV7XWvA==","signatures":[{"sig":"MEQCIGJUSFYA79HuOUq7AGEFzl/asn5/SIgMwwV9DGe1YY2rAiACdq7yBbUcm5xgWbuBC2Ee6Id/fB4RI2bjYNQpxyDbeg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDMegXJI4ZLk793HMo0e2hZcOj5sA0JmIETI3cJKCXkjwIgMjOhGefS3bl10jVdi05BXoBYY0AYEWxpUz546bT7a20="}],"unpackedSize":1620681},"main":"./dist/index.js","name":"@agentwares/agentguard","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"8aee1477cb5ed20954123c11b576f8066418c326","license":"MIT","mcpName":"io.github.agentwares/agentguard","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","listing":"node scripts/generate-listing.mjs","typecheck":"tsc --noEmit","conformance":"node scripts/conformance.mjs"},"version":"0.1.5","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e59feed7-a1f7-404a-8d69-891e8d9b2208"}},"homepage":"https://github.com/agentwares/agentguard#readme","keywords":["mcp","mcp-proxy","model-context-protocol","ai-agents","agent-safety","spend-limit","kill-switch","dry-run","audit-log","claude-code","cursor","guardrails"],"repository":{"url":"git+https://github.com/agentwares/agentguard.git","type":"git","directory":"apps/agentguard-cli"},"_npmVersion":"12.0.2","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, ","directories":{},"maintainers":[{"name":"umerbukhari","email":"umer.bukhari@gmail.com"}],"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.5.4","yaml":"^2.9.0","@modelcontextprotocol/sdk":"^1.30.0","@agentwares/agentguard-core":"^0.1.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","@agentwares/notify":"workspace:^","@agentwares/mcp-kit":"workspace:^"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agentguard_0.1.5_1789149233151_0.4100167117591613"}}},"time":{"created":"2026-09-04T00:57:05.772Z","modified":"2026-09-11T17:53:54.120Z","0.1.0":"2026-09-04T00:57:06.079Z","0.1.1":"2026-09-07T18:50:29.147Z","0.1.2":"2026-09-07T18:54:25.932Z","0.1.3":"2026-09-07T22:36:20.213Z","0.1.4":"2026-09-11T17:43:03.570Z","0.1.5":"2026-09-11T17:53:53.264Z"},"bugs":{"url":"https://github.com/agentwares/agentguard/issues"},"license":"MIT","homepage":"https://github.com/agentwares/agentguard#readme","keywords":["mcp","mcp-proxy","model-context-protocol","ai-agents","agent-safety","spend-limit","kill-switch","dry-run","audit-log","claude-code","cursor","guardrails"],"repository":{"url":"git+https://github.com/agentwares/agentguard.git","type":"git","directory":"apps/agentguard-cli"},"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, ","maintainers":[{"name":"umerbukhari","email":"umer.bukhari@gmail.com"}],"readme":"# agentguard\n\n**60 seconds to a safe first run.** Your agent already has an MCP config. Put agentguard in front of it, run the agent once in dry-run, and read what it _would_ have done:\n\n```sh\nnpx @agentwares/agentguard init          # finds your MCP config, writes agentguard.yaml (dry-run), routes every server through the proxy\n# restart your MCP client, run your agent as usual — writes are faked, nothing executes upstream\nnpx @agentwares/agentguard report        # \"would have deleted 12 records, sent 5 emails, spent $140 — halted a loop at call 31\"\nnpx @agentwares/agentguard diff          # the record-by-record mutation diff\n# set `mode: enforce` in agentguard.yaml when it looks right\n```\n\n```\n# agentguard report — run `run_20260902_a1b2`\n\n61 tool calls between 10:02:11 and 10:02:19 across crm.\n\n## What this run would have done (dry-run, nothing was executed)\n\nIt would have **deleted 1 record**, updated 1, created 1, sent 1 message, **spent $12.00**.\n\n## Where agentguard stepped in\n\n| #  | code            | tool               | why                                                          |\n|----|-----------------|--------------------|--------------------------------------------------------------|\n| 10 | `LOOP_DETECTED` | crm_update_contact | called 3 times with the same arguments in the last 30 calls  |\n| 61 | `CAP_EXCEEDED`  | crm_create_contact | writes cap for this run is 50; used 50, this call would make it 51 |\n```\n\nagentguard is an MCP policy proxy for agents that touch production. It sits between the agent and its MCP servers, sees every tool call, and enforces one YAML file:\n\n- **Hard spend limits** — per-run and per-day `spend_usd` across every provider, from tool arguments (`stripe_create_charge.amount`), tool results (`cost_usd`), and — with the SDK's guarded `fetch` — LLM token usage from OpenAI, Anthropic and Gemini responses. The call that would exceed the cap gets `CAP_EXCEEDED` with the remaining budget.\n- **Destructive-action gating with approvals** — `approval.tools: [crm_delete_*]` makes the agent get `APPROVAL_REQUIRED` + an id; a human runs `agentguard approve <id>` (or clicks the button in Slack) and the agent's identical retry goes through once.\n- **Kill switch** — `agentguard kill` (a file), `AGENTGUARD_KILL=1` (env), or `POST /kill` (HTTP): every run halts instantly with `KILLED` until `agentguard resume`.\n- **Per-agent scoped credentials** — the proxy holds the upstream tokens; each agent gets an `agk_…` key with its own allowlist, denylist and caps. Only the key's hash lives in the policy.\n- **Dry-run writes with mutation diffs** — classified writes return a plausible success shaped by the tool's output schema so the agent keeps going; `agentguard diff` shows what would have changed.\n- **Semantic loop breaker** — the same `(tool, normalized args)` 3× in the last 30 calls, or an A→B→A→B cycle, returns `LOOP_DETECTED`. Timestamps, ids, whitespace and key order are ignored.\n- **Blast-radius caps** — `tool_calls`, `writes`, `deletes`, `emails`, `spend_usd` and custom counters, per run and per day.\n- **Hash-chained audit log** — every call is a JSONL line with `prev_hash` and `hash`; `agentguard verify` proves no entry was edited, removed from the middle, or reordered (see Limits for what a local chain cannot prove on its own).\n\nNo LLM calls. No phone-home. No account. MIT.\n\nTwo install paths, one policy engine: the **MCP proxy** (`npx @agentwares/agentguard`, stdio + Streamable HTTP, multiple upstreams) and the **SDK/middleware** ([`@agentwares/agentguard-sdk`](https://github.com/agentwares/agentguard/tree/main/packages/agentguard-sdk#readme)) for OpenAI Agents SDK, LangChain or plain-function tools that never go through MCP.\n\n## Install\n\n```sh\nnpx @agentwares/agentguard init                                  # rewrites the first project-level config it finds\nnpx @agentwares/agentguard init --all                            # ...or every config: .mcp.json, .cursor/mcp.json, .vscode/mcp.json\nnpx @agentwares/agentguard init --client ~/.claude.json          # a user-level config, which --all still leaves alone\nnpx @agentwares/agentguard init --client ~/Library/Application\\ Support/Claude/claude_desktop_config.json   # user-level configs only with --client\nnpx @agentwares/agentguard init --undo                           # restore the backup\n```\n\n`init` writes `agentguard.yaml` next to your config, backs the config up (`*.agentguard-backup`), and replaces its servers with one entry:\n\n```json\n{\n  \"mcpServers\": {\n    \"agentguard\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"agentguard\", \"proxy\", \"--config\", \"/abs/path/agentguard.yaml\"]\n    }\n  }\n}\n```\n\nTools keep their names (prefixed `<upstream>__` only on collision). Your MCP client sees one server; agentguard connects to all of them and holds their credentials.\n\nSpawned with no arguments at all — what an install from the MCP registry does — `agentguard` serves the same stdio proxy and reads `AGENTGUARD_CONFIG` or `./agentguard.yaml`. In a terminal it prints the help instead.\n\nPrefer HTTP (several agents, scoped keys, Slack approve buttons)? `agentguard proxy --http --port 8788` and point clients at `http://127.0.0.1:8788/mcp` with an `X-Run-Id` header per run and `Authorization: Bearer agk_…` per agent.\n\n## Policy\n\n`agentguard init` generates this file with every knob explained inline. The short form:\n\n```yaml\nversion: 1\nmode: dry-run                     # dry-run | enforce\nupstreams:\n  - name: crm\n    url: https://mcp.example.com/mcp\n    auth: ${CRM_TOKEN}            # the agent never sees this\n  - name: files\n    command: npx\n    args: [-y, \"@modelcontextprotocol/server-filesystem\", \".\"]\nclassify:                         # patterns win over annotations win over verb heuristics\n  write: [crm_update_*, crm_delete_*, email_send]\n  spend: [stripe_*, x402_*]\n  unknown: write                  # unclassifiable tools count as writes (or: read | block)\ncaps:\n  per_run: { writes: 50, deletes: 10, emails: 5, spend_usd: 25, tool_calls: 400 }\n  per_day: { spend_usd: 200 }\nspend:\n  tools:\n    stripe_create_charge: { amount_arg: amount, divisor: 100, currency_arg: currency }\nloop: { window: 30, max_repeats: 3, max_cycle_len: 4, max_read_repeats: 10 }\ndry_run: { tools: [crm_delete_*], synthesize: true }      # always fake these, even in enforce\napproval:\n  tools: [crm_delete_*, db_drop_*]\n  wait_s: 0                       # >0 holds the call open waiting for the decision\n  notify: { slack: ${SLACK_WEBHOOK_URL} }\nkill: { file: .agentguard/KILL, env: AGENTGUARD_KILL }\nagents:                           # agentguard key create deployer --allow 'crm_get_*' --writes 5\n  - name: deployer\n    key_hash: sha256:…\n    allow: [crm_get_*, crm_update_contact]\n    caps: { per_run: { writes: 5 } }\nalerts: { slack: ${SLACK_WEBHOOK_URL}, on: [LOOP_DETECTED, CAP_EXCEEDED, KILLED, APPROVAL_REQUIRED] }\naudit: { path: .agentguard/audit.jsonl, redact: true }\n```\n\nClassification order: `classify.*` patterns → MCP `annotations.readOnlyHint` / `destructiveHint` → verb heuristics (`get/list/search…` read, `create/update/delete/send/execute…` write, `pay/charge/refund…` + `stripe_*`/`x402_*` spend). `agentguard tools` prints every tool with its class and why.\n\n## What the agent sees\n\nEvery block is an in-band tool result with `isError: true` and a JSON body the model can act on:\n\n```json\n{\n  \"code\": \"CAP_EXCEEDED\",\n  \"cause\": \"writes cap for this run is 50; used 50, this call would make it 51\",\n  \"fix\": \"stop and report to the user what is done and what remains; a human can raise caps.per_run in agentguard.yaml or start a new run\",\n  \"retryable\": false,\n  \"details\": {\n    \"scope\": \"per_run\",\n    \"counter\": \"writes\",\n    \"limit\": 50,\n    \"used\": 50,\n    \"remaining\": { \"writes\": { \"per_run\": 0 } }\n  }\n}\n```\n\nCodes: `KILLED`, `APPROVAL_REQUIRED` (retryable once approved), `APPROVAL_DENIED`, `LOOP_DETECTED`, `CAP_EXCEEDED`, `TOOL_DENIED`, `UNKNOWN_TOOL`, `UPSTREAM_ERROR`. Successful and faked results carry `_meta.agentguard = { class, verb, mode, outcome, dryRun, seq, run_id }`.\n\nRun identity: `X-Run-Id` header (HTTP) → `_meta.runId` on the call → session → one id per proxy process. Per-run caps and the loop window are per run; per-day caps are per policy (and per agent).\n\n## Commands\n\n| Command                                                                                                                         | What it does                                                                                                                                            |\n| ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `agentguard init [--client path] [--all] [--no-probe] [--mode enforce] [--undo]`                                                | generate the policy, rewrite the client config (project-level by default)                                                                               |\n| `agentguard proxy [--http --port 8788] [--agent name] [--run-id id] [--mode m]`                                                 | run the proxy (stdio default)                                                                                                                           |\n| `agentguard report [--run id \\| --all] [--json]`                                                                                | what this run did / would have destroyed / spent; where it was halted; chain status                                                                     |\n| `agentguard diff [--run id]`                                                                                                    | mutation diff of faked writes                                                                                                                           |\n| `agentguard verify [audit.jsonl]`                                                                                               | recompute the hash chain; exit 1 on the first break                                                                                                     |\n| `agentguard status [--run id]`                                                                                                  | counters vs caps, kill state, pending approvals, running HTTP proxy                                                                                     |\n| `agentguard tools [--json]`                                                                                                     | every exposed tool with class, verb, upstream and the reason                                                                                            |\n| `agentguard kill [reason]` / `agentguard resume`                                                                                | halt everything now / clear it                                                                                                                          |\n| `agentguard approvals [--all]` / `approve <id>` / `deny <id> [--note …]`                                                        | the approval queue                                                                                                                                      |\n| `agentguard key create <agent> [--allow p]… [--deny p] [--writes n] [--spend n] [--mode m]` / `key list` / `key revoke <agent>` | scoped credentials                                                                                                                                      |\n| `agentguard connect <key> [--write] [--client path] [--all] [--url base]`                                                       | point this machine's MCP client at a hosted proxy (paid tiers); prints the config, `--write` merges it in                                               |\n| `agentguard permission-diff [--base ref] [--head ref] [--fail-on-widen]`                                                        | which config changes widen agent permissions (also a [GitHub Action](https://github.com/agentwares/agentguard/tree/main/assets/permission-diff-action)) |\n\n### Hosted tiers\n\nThe CLI enforces policy on your machine and needs no account. The paid tiers move enforcement\nserver-side — shared state across machines, retained audit, alerting — and `connect` is how you\npoint a client at yours:\n\n```sh\nnpx @agentwares/agentguard connect agk_...            # print the MCP server block\nnpx @agentwares/agentguard connect agk_... --write    # merge it into your MCP config (existing servers are kept)\n```\n\nUnlike `init`, `connect` adds one remote server and leaves the rest of your config alone. The key\ncomes from your dashboard; everything else — proxy URL, mode, band — is answered by the server.\n\nHTTP control endpoints (token in `.agentguard/http.json`): `GET /health`, `GET /status?run=`, `POST /kill`, `POST /resume`, `GET|POST /approve/:id`, `/deny/:id`, `GET /approvals`.\n\n## Try it with the fixtures\n\n```sh\ngit clone https://github.com/agentwares/agentguard && cd agentguard && pnpm install && pnpm build\ncd apps/agentguard-cli\ncat > agentguard.yaml <<'YAML'\nmode: dry-run\nupstreams:\n  - name: crm\n    command: node\n    args: [dist/fixtures/crm-server.js]\ncaps: { per_run: { writes: 50 } }\nYAML\nnode dist/fixtures/demo-agent.js --config agentguard.yaml   # a scripted agent: reads, writes, a deliberate loop, a 60-write burst\nnode dist/cli.js report && node dist/cli.js diff && node dist/cli.js verify\n```\n\n## Conformance and tests\n\n`pnpm test` runs the CLI suite (24 tests; 64 more in `agentguard-core`, 10 in the SDK): the engine over InMemoryTransport, the spawned stdio proxy, the Streamable HTTP proxy with `X-Run-Id`, scoped keys and control endpoints, `init` against real configs, and a recorded-fixture replay (`fixtures/recorded/crm-session.json`; re-record with `RECORD_FIXTURES=1`). `pnpm conformance` runs the official `@modelcontextprotocol/conformance` server suite against the proxy with a sample server behind it (tools, resources, prompts, completions, logging, progress, sampling and elicitation are relayed).\n\n## Limits (honest)\n\n- The proxy sees MCP tool calls. Token spend on the model API is only visible through the SDK's guarded `fetch` (or `spend.tools` rules for MCP tools that call models).\n- Dry-run synthesizes results from the tool's `outputSchema`; agents that depend on real ids from a create → update chain will see plausible but fake ids. `dry_run.tools` lets you fake only the dangerous tools in enforce mode.\n- Per-day counters are a JSON file under a directory lock; fine for a workstation or one box, not a fleet. The hosted tier (coming) is the shared-state version.\n- Slack \"Approve\" buttons are links to the local HTTP proxy; they work for people who can reach it. Without HTTP mode the message carries the `agentguard approve <id>` command.\n- A local hash chain is tamper-**evident**, not tamper-proof, and it has one blind spot: entries deleted from the **end** of the file leave a shorter chain that still verifies. Editing, deleting from the middle, and reordering are all caught. `agentguard verify` prints the head hash and the entry count — record them (CI log, ticket, chat) to close the gap, or use the hosted tier, which publishes a daily Merkle root you can check the run against.\n\n## Related\n\n- [`@agentwares/agentguard-sdk`](https://github.com/agentwares/agentguard/tree/main/packages/agentguard-sdk#readme) — the same engine for OpenAI Agents SDK / LangChain / plain functions, plus the guarded `fetch` for LLM spend.\n- [`@agentwares/agentguard-core`](https://github.com/agentwares/agentguard/tree/main/packages/agentguard-core#readme) — the Web-standard policy engine (bring your own stores).\n- [permission-diff GitHub Action](https://github.com/agentwares/agentguard/tree/main/assets/permission-diff-action) — comments on PRs that widen `agentguard.yaml`, `.claude/settings.json` or `mcp.json`.\n","readmeFilename":"README.md"}