protect-mcp 0.2.2 → 0.3.1
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/README.md +11 -1
- package/dist/bundle-TXOTFJIJ.mjs +8 -0
- package/dist/chunk-5JXFV37Y.mjs +53 -0
- package/dist/chunk-U7TMVD3E.mjs +1105 -0
- package/dist/cli.js +1176 -172
- package/dist/cli.mjs +462 -5
- package/dist/demo-server.d.mts +1 -0
- package/dist/demo-server.d.ts +1 -0
- package/dist/demo-server.js +137 -0
- package/dist/demo-server.mjs +136 -0
- package/dist/index.d.mts +83 -61
- package/dist/index.d.ts +83 -61
- package/dist/index.js +637 -271
- package/dist/index.mjs +7 -172
- package/package.json +3 -3
- package/dist/chunk-ZCKNFULF.mjs +0 -613
package/README.md
CHANGED
|
@@ -7,6 +7,9 @@ Security gateway for MCP servers. Shadow-mode logs by default, per-tool policies
|
|
|
7
7
|
## Quick Start
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
+
# Wrap an existing OpenClaw / MCP config into a usable pack
|
|
11
|
+
npx @scopeblind/passport wrap --runtime openclaw --config ./openclaw.json --policy email-safe
|
|
12
|
+
|
|
10
13
|
# Shadow mode — log every tool call, enforce nothing
|
|
11
14
|
npx protect-mcp -- node my-server.js
|
|
12
15
|
|
|
@@ -18,6 +21,9 @@ npx protect-mcp --policy protect-mcp.json -- node my-server.js
|
|
|
18
21
|
|
|
19
22
|
# Enforce mode
|
|
20
23
|
npx protect-mcp --policy protect-mcp.json --enforce -- node my-server.js
|
|
24
|
+
|
|
25
|
+
# Export an offline-verifiable audit bundle
|
|
26
|
+
npx protect-mcp bundle --output audit.json
|
|
21
27
|
```
|
|
22
28
|
|
|
23
29
|
## What It Does
|
|
@@ -39,7 +45,7 @@ All other MCP messages (`initialize`, `tools/list`, notifications) pass through
|
|
|
39
45
|
|
|
40
46
|
- **Per-tool policies** — block destructive tools, rate-limit expensive ones, and attach minimum-tier requirements
|
|
41
47
|
- **Structured decision logs** — every decision is emitted to `stderr` with `[PROTECT_MCP]`
|
|
42
|
-
- **Optional local signed receipts** — generated when you run with a policy containing `signing.key_path`
|
|
48
|
+
- **Optional local signed receipts** — generated when you run with a policy containing `signing.key_path`, persisted to `.protect-mcp-receipts.jsonl`, and exposed at `http://127.0.0.1:9876/receipts`
|
|
43
49
|
- **Offline verification** — verify receipts or bundles with `npx @veritasacta/verify`
|
|
44
50
|
- **No account required** — local keys, local policy, local process
|
|
45
51
|
|
|
@@ -123,6 +129,10 @@ protect-mcp init
|
|
|
123
129
|
|
|
124
130
|
Commands:
|
|
125
131
|
init Generate Ed25519 keypair + config template
|
|
132
|
+
status Show decision stats and local passport identity
|
|
133
|
+
digest Generate a local human-readable summary
|
|
134
|
+
receipts Show recent persisted signed receipts
|
|
135
|
+
bundle Export an offline-verifiable audit bundle
|
|
126
136
|
|
|
127
137
|
Options:
|
|
128
138
|
--policy <path> Policy/config JSON file
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/bundle.ts
|
|
2
|
+
function createAuditBundle(opts) {
|
|
3
|
+
const receipts = opts.receipts.filter(
|
|
4
|
+
(r) => r && typeof r === "object" && typeof r.signature === "string"
|
|
5
|
+
);
|
|
6
|
+
if (receipts.length === 0) {
|
|
7
|
+
throw new Error("Audit bundle requires at least one signed receipt");
|
|
8
|
+
}
|
|
9
|
+
const keyMap = /* @__PURE__ */ new Map();
|
|
10
|
+
for (const key of opts.signingKeys) {
|
|
11
|
+
if (!keyMap.has(key.kid)) {
|
|
12
|
+
keyMap.set(key.kid, key);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
let timeRange = opts.timeRange || null;
|
|
16
|
+
if (!timeRange) {
|
|
17
|
+
const timestamps = receipts.map((r) => r.issued_at || r.timestamp).filter(Boolean).sort();
|
|
18
|
+
if (timestamps.length > 0) {
|
|
19
|
+
timeRange = {
|
|
20
|
+
from: timestamps[0],
|
|
21
|
+
to: timestamps[timestamps.length - 1]
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
format: "scopeblind:audit-bundle",
|
|
27
|
+
version: 1,
|
|
28
|
+
exported_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29
|
+
tenant: opts.tenant,
|
|
30
|
+
time_range: timeRange,
|
|
31
|
+
receipts,
|
|
32
|
+
anchors: opts.anchors || [],
|
|
33
|
+
verification: {
|
|
34
|
+
algorithm: "ed25519",
|
|
35
|
+
signing_keys: Array.from(keyMap.values()),
|
|
36
|
+
instructions: `Verify each receipt by: (1) remove the "signature" field, (2) canonicalize the remaining object with JCS (sorted keys at every level), (3) encode as UTF-8 bytes, (4) verify the Ed25519 signature using the signing key matching the receipt's "kid" field. CLI: npx @veritasacta/verify bundle.json --bundle`
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function collectSignedReceipts(logs) {
|
|
41
|
+
return logs.filter((log) => log.v === 2).map((log) => {
|
|
42
|
+
const logRecord = log;
|
|
43
|
+
if (logRecord.receipt) {
|
|
44
|
+
return logRecord.receipt;
|
|
45
|
+
}
|
|
46
|
+
return logRecord;
|
|
47
|
+
}).filter((r) => typeof r.signature === "string");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
createAuditBundle,
|
|
52
|
+
collectSignedReceipts
|
|
53
|
+
};
|