protect-mcp 0.7.2 → 0.7.4
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 +69 -0
- package/README.md +157 -9
- package/dist/{bundle-XTR3YMPO.mjs → bundle-YUUHAG7O.mjs} +1 -1
- package/dist/chunk-36UID5WY.mjs +662 -0
- package/dist/{chunk-546U3A7R.mjs → chunk-D2RDY2JR.mjs} +92 -1
- package/dist/chunk-F2FKQ4XN.mjs +410 -0
- package/dist/{chunk-J6L4XCTE.mjs → chunk-KPSICBAJ.mjs} +75 -0
- package/dist/{chunk-X63ELMU4.mjs → chunk-NVJHGXXG.mjs} +37 -7
- package/dist/{chunk-5JXFV37Y.mjs → chunk-PM2ZO57M.mjs} +10 -2
- package/dist/{chunk-OHUTUFTC.mjs → chunk-UBZJ3VI2.mjs} +19 -15
- package/dist/cli.js +4034 -502
- package/dist/cli.mjs +2028 -9
- package/dist/demo-server.d.mts +3 -0
- package/dist/demo-server.d.ts +3 -0
- package/dist/demo-server.js +75 -0
- package/dist/demo-server.mjs +1 -1
- package/dist/hook-server.js +144 -25
- package/dist/hook-server.mjs +2 -2
- package/dist/{http-transport-R5AO7X6D.mjs → http-transport-4GMMRPW7.mjs} +2 -2
- package/dist/index.d.mts +115 -1
- package/dist/index.d.ts +115 -1
- package/dist/index.js +988 -80
- package/dist/index.mjs +48 -249
- package/dist/receipt-registry-6CAOY6RP.mjs +279 -0
- package/dist/signing-committed-MMLJ6OGG.mjs +15 -0
- package/package.json +1 -1
- package/dist/chunk-ZBKJANP7.mjs +0 -145
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSelectiveDisclosurePackage,
|
|
3
|
+
discloseField,
|
|
4
|
+
signCommittedDecision,
|
|
5
|
+
verifySelectiveDisclosurePackage
|
|
6
|
+
} from "./chunk-F2FKQ4XN.mjs";
|
|
7
|
+
import "./chunk-LYKNULYU.mjs";
|
|
8
|
+
import "./chunk-D733KAPG.mjs";
|
|
9
|
+
import "./chunk-PQJP2ZCI.mjs";
|
|
10
|
+
export {
|
|
11
|
+
createSelectiveDisclosurePackage,
|
|
12
|
+
discloseField,
|
|
13
|
+
signCommittedDecision,
|
|
14
|
+
verifySelectiveDisclosurePackage
|
|
15
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "protect-mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"mcpName": "com.scopeblind/protect-mcp",
|
|
5
5
|
"description": "Fail-closed Cedar policy gate + signed receipts for AI agent tool calls. Blocks what breaks the rules before it runs, denies on any policy error, and proves the gate is live with a startup self-test.",
|
|
6
6
|
"main": "dist/index.js",
|
package/dist/chunk-ZBKJANP7.mjs
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
meetsMinTier
|
|
3
|
-
} from "./chunk-OHUTUFTC.mjs";
|
|
4
|
-
import {
|
|
5
|
-
checkRateLimit,
|
|
6
|
-
getToolPolicy,
|
|
7
|
-
parseRateLimit
|
|
8
|
-
} from "./chunk-546U3A7R.mjs";
|
|
9
|
-
|
|
10
|
-
// src/simulate.ts
|
|
11
|
-
import { readFileSync } from "fs";
|
|
12
|
-
function parseLogFile(path) {
|
|
13
|
-
const raw = readFileSync(path, "utf-8");
|
|
14
|
-
const entries = [];
|
|
15
|
-
for (const line of raw.split("\n")) {
|
|
16
|
-
const trimmed = line.trim();
|
|
17
|
-
if (!trimmed) continue;
|
|
18
|
-
const jsonStr = trimmed.replace(/^\[PROTECT_MCP\]\s*/, "");
|
|
19
|
-
try {
|
|
20
|
-
const parsed = JSON.parse(jsonStr);
|
|
21
|
-
if (parsed.tool && parsed.decision) {
|
|
22
|
-
entries.push(parsed);
|
|
23
|
-
}
|
|
24
|
-
} catch {
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return entries;
|
|
28
|
-
}
|
|
29
|
-
function simulate(entries, policy, tier = "unknown") {
|
|
30
|
-
const rateLimitStore = /* @__PURE__ */ new Map();
|
|
31
|
-
const toolResults = /* @__PURE__ */ new Map();
|
|
32
|
-
const totals = {
|
|
33
|
-
allow: 0,
|
|
34
|
-
block: 0,
|
|
35
|
-
rate_limited: 0,
|
|
36
|
-
require_approval: 0,
|
|
37
|
-
tier_insufficient: 0
|
|
38
|
-
};
|
|
39
|
-
const originalTotals = { allow: 0, deny: 0 };
|
|
40
|
-
const changes = [];
|
|
41
|
-
for (const entry of entries) {
|
|
42
|
-
const toolName = entry.tool;
|
|
43
|
-
const toolPolicy = getToolPolicy(toolName, policy);
|
|
44
|
-
if (entry.decision === "allow") {
|
|
45
|
-
originalTotals.allow++;
|
|
46
|
-
} else {
|
|
47
|
-
originalTotals.deny++;
|
|
48
|
-
}
|
|
49
|
-
let newDecision;
|
|
50
|
-
if (toolPolicy.block) {
|
|
51
|
-
newDecision = "block";
|
|
52
|
-
} else if (toolPolicy.min_tier && !meetsMinTier(tier, toolPolicy.min_tier)) {
|
|
53
|
-
newDecision = "tier_insufficient";
|
|
54
|
-
} else if (toolPolicy.require_approval) {
|
|
55
|
-
newDecision = "require_approval";
|
|
56
|
-
} else if (toolPolicy.rate_limit) {
|
|
57
|
-
const limit = parseRateLimit(toolPolicy.rate_limit);
|
|
58
|
-
const result = checkRateLimit(toolName, limit, rateLimitStore);
|
|
59
|
-
newDecision = result.allowed ? "allow" : "rate_limited";
|
|
60
|
-
} else {
|
|
61
|
-
newDecision = "allow";
|
|
62
|
-
}
|
|
63
|
-
totals[newDecision]++;
|
|
64
|
-
if (!toolResults.has(toolName)) {
|
|
65
|
-
toolResults.set(toolName, {
|
|
66
|
-
tool: toolName,
|
|
67
|
-
calls: 0,
|
|
68
|
-
results: { allow: 0, block: 0, rate_limited: 0, require_approval: 0, tier_insufficient: 0 },
|
|
69
|
-
original: { allow: 0, deny: 0 }
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
const tr = toolResults.get(toolName);
|
|
73
|
-
tr.calls++;
|
|
74
|
-
tr.results[newDecision]++;
|
|
75
|
-
if (entry.decision === "allow") {
|
|
76
|
-
tr.original.allow++;
|
|
77
|
-
} else {
|
|
78
|
-
tr.original.deny++;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
for (const [tool, result] of toolResults) {
|
|
82
|
-
const wasAllBlocked = result.original.allow === 0;
|
|
83
|
-
const nowAllBlocked = result.results.allow === 0;
|
|
84
|
-
const wasAllAllowed = result.original.deny === 0;
|
|
85
|
-
if (wasAllAllowed && result.results.block > 0) {
|
|
86
|
-
changes.push(`${tool}: ${result.results.block} calls would be blocked (was: all allowed)`);
|
|
87
|
-
}
|
|
88
|
-
if (wasAllAllowed && result.results.rate_limited > 0) {
|
|
89
|
-
changes.push(`${tool}: ${result.results.rate_limited} calls would be rate-limited (was: all allowed)`);
|
|
90
|
-
}
|
|
91
|
-
if (wasAllAllowed && result.results.require_approval > 0) {
|
|
92
|
-
changes.push(`${tool}: ${result.results.require_approval} calls would require approval (was: all allowed)`);
|
|
93
|
-
}
|
|
94
|
-
if (wasAllAllowed && result.results.tier_insufficient > 0) {
|
|
95
|
-
changes.push(`${tool}: ${result.results.tier_insufficient} calls would fail tier check (was: all allowed)`);
|
|
96
|
-
}
|
|
97
|
-
if (wasAllBlocked && result.results.allow > 0 && !nowAllBlocked) {
|
|
98
|
-
changes.push(`${tool}: ${result.results.allow} calls would now be allowed (was: all blocked)`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
policy_file: "",
|
|
103
|
-
log_file: "",
|
|
104
|
-
total_calls: entries.length,
|
|
105
|
-
results: totals,
|
|
106
|
-
original: originalTotals,
|
|
107
|
-
tool_breakdown: Array.from(toolResults.values()).sort((a, b) => b.calls - a.calls),
|
|
108
|
-
changes
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
function formatSimulation(summary) {
|
|
112
|
-
const lines = [];
|
|
113
|
-
lines.push(`Simulating ${summary.policy_file} against ${summary.total_calls} recorded tool calls:
|
|
114
|
-
`);
|
|
115
|
-
const maxToolLen = Math.max(...summary.tool_breakdown.map((t) => t.tool.length), 4);
|
|
116
|
-
for (const tr of summary.tool_breakdown) {
|
|
117
|
-
const parts = [];
|
|
118
|
-
if (tr.results.allow > 0) parts.push(`${tr.results.allow} allow`);
|
|
119
|
-
if (tr.results.block > 0) parts.push(`\x1B[31m${tr.results.block} blocked\x1B[0m`);
|
|
120
|
-
if (tr.results.rate_limited > 0) parts.push(`\x1B[33m${tr.results.rate_limited} rate_limited\x1B[0m`);
|
|
121
|
-
if (tr.results.require_approval > 0) parts.push(`\x1B[36m${tr.results.require_approval} require_approval\x1B[0m`);
|
|
122
|
-
if (tr.results.tier_insufficient > 0) parts.push(`\x1B[35m${tr.results.tier_insufficient} tier_insufficient\x1B[0m`);
|
|
123
|
-
const originalParts = [];
|
|
124
|
-
if (tr.original.allow > 0) originalParts.push(`${tr.original.allow} allow`);
|
|
125
|
-
if (tr.original.deny > 0) originalParts.push(`${tr.original.deny} deny`);
|
|
126
|
-
lines.push(` ${tr.tool.padEnd(maxToolLen)} \xD7 ${String(tr.calls).padStart(3)} \u2192 ${parts.join(", ")} (was: ${originalParts.join(", ")})`);
|
|
127
|
-
}
|
|
128
|
-
lines.push("");
|
|
129
|
-
lines.push(`Summary: ${summary.results.allow} allow, ${summary.results.block} blocked, ${summary.results.rate_limited} rate_limited, ${summary.results.require_approval} require_approval, ${summary.results.tier_insufficient} tier_insufficient`);
|
|
130
|
-
lines.push(` vs original: ${summary.original.allow} allow, ${summary.original.deny} deny`);
|
|
131
|
-
if (summary.changes.length > 0) {
|
|
132
|
-
lines.push("");
|
|
133
|
-
lines.push("Changes:");
|
|
134
|
-
for (const change of summary.changes) {
|
|
135
|
-
lines.push(` \u2022 ${change}`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return lines.join("\n");
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export {
|
|
142
|
-
parseLogFile,
|
|
143
|
-
simulate,
|
|
144
|
-
formatSimulation
|
|
145
|
-
};
|