protect-mcp 0.7.3 → 0.7.5

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 CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.4: the self-serve trial path
4
+
5
+ Everything the scopeblind.com trial and docs pages describe now ships in the
6
+ published package: wrap, dashboard, trial, policy packs, connectors, the
7
+ registry client, and selective disclosure v0.
8
+
9
+ - Added `protect-mcp trial`, a guided ten-minute local trial: run the demo
10
+ tool server, watch risky calls, install a policy pack, require an approval,
11
+ and export a signed receipt you can verify offline.
12
+ - Added `protect-mcp connectors`, dry-run connector pilots for GitHub, email,
13
+ filesystem/Git, Slack or Teams, and a mock-to-real PMS adapter
14
+ (`connectors list|show|init|doctor`). These are scaffolds with policies and
15
+ config, not a managed marketplace; GitHub, Slack/Teams, and real PMS mode
16
+ still need customer tokens or adapters.
17
+ - Added `protect-mcp wrap` for install-to-aha onboarding. It prints a protected
18
+ MCP command, can patch Claude Desktop MCP server config in dry-run mode, and
19
+ writes only when `--write` is passed.
20
+ - Added `protect-mcp dashboard`, a local-only `127.0.0.1` dashboard for
21
+ shadow-mode inventory, risk review, receipts, and next policy moves.
22
+ - Added exact-action readbacks to decision logs and signed receipts: tool,
23
+ action, destination, redacted payload preview, payload hash, disclosed fields,
24
+ and redacted fields.
25
+ - Upgraded the local dashboard into an action-control surface: policy coverage,
26
+ one-click `Require approval`/`Block`/`Observe` drafting, pending approval
27
+ queue, reason capture, desktop approval forwarding, receipt-chain view, and
28
+ audit-bundle export with explicit signed-receipt preflight.
29
+ - Added `protect-mcp recommend`, which drafts a reviewable JSON policy from
30
+ observed local tool calls before users flip wrappers into `--enforce`.
31
+ - Added `protect-mcp registry`, a paid-boundary MVP for hosted org identity,
32
+ receipt digest anchoring, org public-key directory, billing-account metadata,
33
+ and a static verifier page. Hosted mode uploads digests only, not raw prompts,
34
+ payloads, outputs, private keys, or raw receipts.
35
+ - Added `protect-mcp killer-demo`, which generates a three-minute
36
+ shadow-mode → policy → exact approval → gateway execution → signed receipt →
37
+ tamper failure → selective-disclosure demo pack.
38
+ - Added Selective Disclosure v0 on committed receipts: `committed_fields_root`,
39
+ multi-field disclosure packages, verifier explanations for disclosed versus
40
+ hidden fields, CLI verification via `protect-mcp verify-disclosure`, and audit
41
+ bundle inclusion. This is salted commitments + Merkle proofs, not full ZK.
42
+ - Added `protect-mcp policy-packs`, a starter Cedar template library for
43
+ filesystem-safe, Git-safe, email-safe, database-safe, cloud-spend-safe,
44
+ secrets-safe, and finance-mandate-safe rollouts.
45
+ - Expanded the built-in demo MCP server with GitHub PR, email, and mock PMS
46
+ booking tools so the demo maps to agent actions a hedge fund actually cares
47
+ about.
48
+ - Reworked the README quickstart around the practical path: initialize, wrap,
49
+ inspect, draft policy, then enforce.
50
+
3
51
  ## 0.7.3: tool input reaches `context.input`, and the hook path fails closed
4
52
 
5
53
  Two correctness fixes for policy authors who rely on the documented Cedar shape.
package/README.md CHANGED
@@ -26,15 +26,136 @@ telemetry of your decisions anywhere, and is MIT licensed.
26
26
  and verifiable offline with [`@veritasacta/verify`](https://www.npmjs.com/package/@veritasacta/verify).
27
27
  No vendor trust required: the math does not care who runs it.
28
28
 
29
- ## Quickstart (30 seconds)
29
+ ## Quickstart: install to first useful proof
30
30
 
31
31
  ```bash
32
- # 1. Generate an Ed25519 keypair, a config template, and a sample policy.
32
+ # 1. Generate an Ed25519 keypair, config template, and sample policy.
33
33
  npx protect-mcp init
34
34
 
35
- # 2. Put a Cedar policy in ./cedar (see "Write a policy" below), then serve
36
- # the Claude Code hook gate in enforce mode. It runs a restraint self-test
37
- # first and refuses to start if it cannot prove it denies a forbidden vector.
35
+ # 2. Wrap any MCP server in shadow mode. Nothing is blocked yet; calls are logged.
36
+ npx protect-mcp wrap -- node your-mcp-server.js
37
+
38
+ # 3. Inspect the local-only dashboard: tool inventory, risk, approvals, receipts.
39
+ npx protect-mcp dashboard --open
40
+
41
+ # 4. Draft a reviewable policy from observed calls.
42
+ npx protect-mcp recommend --write
43
+
44
+ # 5. When reviewed, restart the wrapper in enforce mode with that policy.
45
+ npx protect-mcp --policy protect-mcp.recommended.json --enforce -- node your-mcp-server.js
46
+ ```
47
+
48
+ For Claude Desktop, run a dry-run config patch first, then apply it:
49
+
50
+ ```bash
51
+ npx protect-mcp wrap --claude-desktop
52
+ npx protect-mcp wrap --claude-desktop --write
53
+ npx protect-mcp dashboard --open
54
+ ```
55
+
56
+ The dashboard binds to `127.0.0.1`, reads only local log/receipt files, and does
57
+ not upload anything. Use `npx protect-mcp connect` only if you explicitly want a
58
+ hosted ScopeBlind dashboard.
59
+
60
+ ### Local Action Dashboard
61
+
62
+ `protect-mcp dashboard` is the operator view for moving from visibility to
63
+ enforcement:
64
+
65
+ - **Tool inventory:** every observed tool, call count, high/medium/low risk, and
66
+ whether the active policy has an exact rule, a wildcard fallback, or no rule.
67
+ - **Policy coverage:** one-click local policy edits for `Require approval`,
68
+ `Block`, or `Observe`. Restart the wrapper after reviewing changes.
69
+ - **Exact-action approval queue:** the exact tool, action, destination, redacted
70
+ payload preview, payload hash, policy basis, and reason capture before a human
71
+ approves, denies, edits, or takes over.
72
+ - **Receipt chain:** request ids correlated with signed receipt hashes, so an
73
+ audit reviewer can see which decisions have cryptographic proof.
74
+ - **Audit export:** downloads the offline-verifiable audit bundle when signed
75
+ receipts exist. If only unsigned local logs exist, the dashboard explains that
76
+ signing must be enabled first.
77
+
78
+ For live desktop fallback approvals, start the dashboard with the local gateway
79
+ approval endpoint and nonce printed by the wrapper:
80
+
81
+ ```bash
82
+ npx protect-mcp dashboard --open \
83
+ --approval-endpoint http://127.0.0.1:9876 \
84
+ --approval-nonce "$PROTECT_MCP_APPROVAL_NONCE"
85
+ ```
86
+
87
+ `Approve` forwards to the live local gateway when those flags are present.
88
+ `Deny`, `Edit`, and `Take over` are recorded locally as approval-resolution
89
+ records; use them as the operator instruction and rerun the tool when needed.
90
+
91
+ ### Paid Boundary MVP: digest anchoring, not data upload
92
+
93
+ Local self-signed receipts stay free and offline-verifiable. The paid boundary is
94
+ independent evidence that ScopeBlind saw a receipt digest at a time, under an org
95
+ identity, without receiving the raw prompt, tool payload, output, private key, or
96
+ raw receipt.
97
+
98
+ ```bash
99
+ # Create or refresh a local org identity and public-key directory.
100
+ npx protect-mcp registry init --org "Meridian Global Macro" --billing-account acct_meridian
101
+
102
+ # Local preview: writes a digest registry and shareable static verifier page.
103
+ npx protect-mcp registry anchor
104
+
105
+ # Hosted mode: uploads receipt digests only for independent anchoring.
106
+ SCOPEBLIND_TOKEN=... npx protect-mcp registry anchor \
107
+ --hosted \
108
+ --endpoint https://api.scopeblind.com \
109
+ --verifier-base https://legate.scopeblind.com
110
+ ```
111
+
112
+ The local preview is deliberately labeled `local-preview-not-independent`.
113
+ Hosted mode anchors only receipt hashes, request ids, org public keys, and
114
+ billing metadata. It does not upload raw receipts or sensitive context.
115
+
116
+ ### Killer Demo: shadow to policy to proof
117
+
118
+ `protect-mcp killer-demo` generates a complete three-minute sales/demo pack:
119
+
120
+ ```bash
121
+ npx protect-mcp killer-demo --dir ./scopeblind-demo
122
+ ```
123
+
124
+ It creates mock filesystem, GitHub, email, and PMS activity; shows risky calls in
125
+ shadow mode; applies a policy pack; requires approval for a sensitive PMS booking;
126
+ executes through the gateway; writes a signed receipt; proves the original
127
+ receipt verifies; proves a tampered receipt fails; and creates a selective
128
+ disclosure package that hides sensitive context while showing the minimum proof.
129
+
130
+ Open the generated `DEMO-RUNBOOK.md` first. Then run the printed dashboard
131
+ command to walk a customer through the exact sequence.
132
+
133
+ ### Selective Disclosure v0
134
+
135
+ Commitment-mode receipts can carry a `committed_fields_root` instead of exposing
136
+ every field in cleartext. Later, the holder can disclose selected fields only:
137
+
138
+ ```bash
139
+ npx protect-mcp verify-disclosure \
140
+ --receipt ./receipts/selective-disclosure.receipt.json \
141
+ --disclosure ./receipts/selective-disclosure.tool-only.json
142
+ ```
143
+
144
+ The verifier checks the parent receipt hash, Ed25519 signature, commitment root,
145
+ and each disclosed field's Merkle proof. It then explains which fields were
146
+ disclosed and which committed fields remain hidden. This is salted commitment
147
+ disclosure, not full zero-knowledge, but it makes the privacy claim concrete:
148
+ auditors can verify selected facts without receiving the full tool payload or
149
+ sensitive desk context.
150
+
151
+ ## Claude Code hook quickstart
152
+
153
+ ```bash
154
+ # Generate hook config and a sample Cedar policy.
155
+ npx protect-mcp init-hooks
156
+
157
+ # Serve the Claude Code hook gate in enforce mode. It runs a restraint self-test
158
+ # first and refuses to start if it cannot prove it denies a forbidden vector.
38
159
  npx protect-mcp serve --enforce --cedar ./cedar
39
160
  ```
40
161
 
@@ -153,8 +274,28 @@ forbid(
153
274
  > CI tripwire test fails the build if the pattern is reintroduced into a shipped
154
275
  > policy. See [GHSA-hm46-7j72-rpv9](https://github.com/ScopeBlind/scopeblind-gateway/security/advisories/GHSA-hm46-7j72-rpv9).
155
276
 
156
- Ready-to-use Cedar packs ship in `policies/cedar/` (Clinejection / CVE-2025-6514,
157
- Terraform destroy, secret-file exfiltration, spending authority).
277
+ ### Starter policy packs
278
+
279
+ Most teams should not write Cedar from scratch on day one. Install a starter
280
+ pack, run in shadow mode, inspect receipts, then tighten or enforce:
281
+
282
+ ```bash
283
+ npx protect-mcp policy-packs list
284
+ npx protect-mcp policy-packs show secrets-safe
285
+ npx protect-mcp policy-packs install filesystem-safe --dir ./cedar
286
+ npx protect-mcp policy-packs install all --dir ./cedar
287
+ npx protect-mcp serve --cedar ./cedar
288
+ ```
289
+
290
+ Built-in packs:
291
+
292
+ - `filesystem-safe`: destructive file actions and secret-like path reads.
293
+ - `git-safe`: force pushes, hard resets, destructive cleanup, repo deletion.
294
+ - `email-safe`: allow drafting, block unattended sends.
295
+ - `database-safe`: read-oriented DB posture, block write/admin SQL.
296
+ - `cloud-spend-safe`: obvious cloud spend creation and infrastructure destruction.
297
+ - `secrets-safe`: common file, env, shell, and cloud secret exfiltration.
298
+ - `finance-mandate-safe`: restricted-list and concentration breaches in booking flows.
158
299
 
159
300
  ## Verify a receipt
160
301
 
@@ -190,6 +331,13 @@ To report a vulnerability, see [SECURITY.md](./SECURITY.md).
190
331
  |---------|-------------|
191
332
  | `serve` | Start the HTTP hook server for Claude Code (port 9377). `--enforce` runs the restraint self-test first; `--cedar <dir>` and `--policy <path>` select the policy. |
192
333
  | `init` | Generate an Ed25519 keypair (`keys/gateway.json`), a config template, and a sample policy. |
334
+ | `wrap` | Print a protected MCP command or patch Claude Desktop MCP servers. Dry-run by default; use `--write` to update Claude Desktop config. |
335
+ | `dashboard` | Start a local-only dashboard on `127.0.0.1` showing tool inventory, risk, policy coverage, exact-action approvals, receipt chains, and audit export. |
336
+ | `recommend` | Draft a reviewable JSON policy from observed local calls. Dry-run by default; use `--write` to create `protect-mcp.recommended.json`. |
337
+ | `registry` | Create an org identity, anchor receipt digests, and write a static verifier page. Hosted mode uploads digests only. |
338
+ | `killer-demo` | Generate a complete shadow-mode to policy to approval to signed-receipt demo pack. |
339
+ | `verify-disclosure` | Verify a `scopeblind.selective_disclosure.v0` package and explain disclosed versus hidden fields. |
340
+ | `policy-packs` | List, inspect, and install starter Cedar policy packs. |
193
341
  | `evaluate` | Evaluate one tool call against a Cedar policy (PreToolUse gate). Exit 2 = deny (fail-closed), exit 0 = allow. |
194
342
  | `sign` | Sign one tool call into a receipt (PostToolUse). Best-effort: records an honest unsigned line if no key. |
195
343
  | `simulate` | Dry-run a policy against a recorded decision log to see what it would have blocked. |
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  collectSignedReceipts,
3
3
  createAuditBundle
4
- } from "./chunk-5JXFV37Y.mjs";
4
+ } from "./chunk-PM2ZO57M.mjs";
5
5
  import "./chunk-PQJP2ZCI.mjs";
6
6
  export {
7
7
  collectSignedReceipts,
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  ReceiptBuffer,
3
+ buildActionReadback,
3
4
  checkRateLimit,
4
5
  evaluateCedar,
5
6
  getSignerInfo,
@@ -11,7 +12,7 @@ import {
11
12
  loadPolicy,
12
13
  parseRateLimit,
13
14
  signDecision
14
- } from "./chunk-546U3A7R.mjs";
15
+ } from "./chunk-WIPWNWMJ.mjs";
15
16
 
16
17
  // src/hook-server.ts
17
18
  import { createServer } from "http";
@@ -241,6 +242,7 @@ async function handlePreToolUse(input, state) {
241
242
  requestId
242
243
  });
243
244
  const payloadDigest = computePayloadDigest(input.toolInput);
245
+ const actionReadback = buildActionReadback(toolName, input.toolInput || {});
244
246
  const swarm = {
245
247
  ...state.swarmContext,
246
248
  ...input.agentId && { agent_id: input.agentId },
@@ -280,6 +282,7 @@ async function handlePreToolUse(input, state) {
280
282
  swarm: swarm.team_name ? swarm : void 0,
281
283
  timing: { hook_latency_ms: hookLatency2, started_at: hookStart },
282
284
  payload_digest: payloadDigest,
285
+ action_readback: actionReadback,
283
286
  deny_iteration: denyCount,
284
287
  sandbox_state: detectSandboxState(),
285
288
  plan_receipt_id: state.activePlanReceiptId || void 0
@@ -314,6 +317,7 @@ async function handlePreToolUse(input, state) {
314
317
  swarm: swarm.team_name ? swarm : void 0,
315
318
  timing: { hook_latency_ms: hookLatency2, started_at: hookStart },
316
319
  payload_digest: payloadDigest,
320
+ action_readback: actionReadback,
317
321
  sandbox_state: detectSandboxState()
318
322
  });
319
323
  return {
@@ -338,6 +342,7 @@ async function handlePreToolUse(input, state) {
338
342
  swarm: swarm.team_name ? swarm : void 0,
339
343
  timing: { hook_latency_ms: hookLatency2, started_at: hookStart },
340
344
  payload_digest: payloadDigest,
345
+ action_readback: actionReadback,
341
346
  sandbox_state: detectSandboxState()
342
347
  });
343
348
  return {
@@ -358,13 +363,15 @@ async function handlePreToolUse(input, state) {
358
363
  hook_event: "PreToolUse",
359
364
  swarm: swarm.team_name ? swarm : void 0,
360
365
  timing: { hook_latency_ms: hookLatency2, started_at: hookStart },
366
+ payload_digest: payloadDigest,
367
+ action_readback: actionReadback,
361
368
  sandbox_state: detectSandboxState()
362
369
  });
363
370
  return {
364
371
  hookSpecificOutput: {
365
372
  hookEventName: "PreToolUse",
366
373
  permissionDecision: "ask",
367
- permissionDecisionReason: `[ScopeBlind] "${toolName}" requires human approval. Policy: ${state.policyDigest}`
374
+ permissionDecisionReason: `[ScopeBlind] Approval required for exactly this action: ${actionReadback.summary}. Payload hash: ${actionReadback.payload_hash.slice(0, 16)}\u2026 Policy: ${state.policyDigest}`
368
375
  }
369
376
  };
370
377
  }
@@ -409,6 +416,7 @@ async function handlePreToolUse(input, state) {
409
416
  swarm: swarm.team_name ? swarm : void 0,
410
417
  timing: { hook_latency_ms: hookLatency, started_at: hookStart },
411
418
  payload_digest: payloadDigest,
419
+ action_readback: actionReadback,
412
420
  sandbox_state: detectSandboxState(),
413
421
  plan_receipt_id: state.activePlanReceiptId || void 0
414
422
  });
@@ -821,7 +829,7 @@ async function startHookServer(options = {}) {
821
829
  res.end(JSON.stringify({
822
830
  status: "ok",
823
831
  server: "protect-mcp-hooks",
824
- version: "0.5.0",
832
+ version: process.env.PROTECT_MCP_VERSION || "unknown",
825
833
  uptime_ms: Date.now() - state.startTime,
826
834
  mode: enforce ? "enforce" : "shadow",
827
835
  policy_digest: policyDigest,
@@ -908,9 +916,10 @@ async function startHookServer(options = {}) {
908
916
  const pad = (s, n = 46) => s.padEnd(n);
909
917
  w(`
910
918
  `);
911
- w(` protect-mcp v0.5.4
919
+ w(process.env.PROTECT_MCP_VERSION ? ` protect-mcp v${process.env.PROTECT_MCP_VERSION}
920
+ ` : ` protect-mcp
912
921
  `);
913
- w(` ScopeBlind \u2014 https://scopeblind.com
922
+ w(` ScopeBlind \xB7 https://scopeblind.com
914
923
  `);
915
924
  w(`
916
925
  `);
@@ -938,7 +947,13 @@ async function startHookServer(options = {}) {
938
947
  `);
939
948
  w(`
940
949
  `);
941
- w(` deny is authoritative \u2014 cannot be overridden.
950
+ w(` deny is authoritative: it cannot be overridden.
951
+ `);
952
+ w(`
953
+ `);
954
+ w(` See your record npx protect-mcp record
955
+ `);
956
+ w(` a searchable view of every decision, all on this machine
942
957
  `);
943
958
  w(`
944
959
  `);