protect-mcp 0.2.0 → 0.2.2

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 CHANGED
@@ -1,20 +1,23 @@
1
1
  # protect-mcp
2
2
 
3
- Security gateway for MCP servers. Tool-level policies, trust-tier gating, credential isolation, and signed decision receipts.
3
+ Security gateway for MCP servers. Shadow-mode logs by default, per-tool policies, optional local Ed25519 receipts, and verification-friendly audit output.
4
4
 
5
- **Shadow mode by default.** Wraps any MCP server as a transparent proxy. Logs every tool call. Signs every decision. Optionally enforces policies.
5
+ **Current CLI path:** wrap any stdio MCP server as a transparent proxy. In shadow mode it logs every `tools/call` request and allows everything through. Add a policy file to enforce per-tool rules. Run `protect-mcp init` to generate local signing keys and config so the gateway can also emit signed receipts.
6
6
 
7
7
  ## Quick Start
8
8
 
9
9
  ```bash
10
- # Shadow mode — log and sign every tool call, enforce nothing
10
+ # Shadow mode — log every tool call, enforce nothing
11
11
  npx protect-mcp -- node my-server.js
12
12
 
13
- # Initialize a new project with keys + config template
13
+ # Generate keys + config template for local signing
14
14
  npx protect-mcp init
15
15
 
16
- # Enforce mode with a policy file
17
- npx protect-mcp --policy policy.json --enforce -- node my-server.js
16
+ # Shadow mode with local signing enabled
17
+ npx protect-mcp --policy protect-mcp.json -- node my-server.js
18
+
19
+ # Enforce mode
20
+ npx protect-mcp --policy protect-mcp.json --enforce -- node my-server.js
18
21
  ```
19
22
 
20
23
  ## What It Does
@@ -26,105 +29,28 @@ MCP Client ←stdin/stdout→ protect-mcp ←stdin/stdout→ your MCP server
26
29
  ```
27
30
 
28
31
  It intercepts `tools/call` JSON-RPC requests and:
29
- - **Shadow mode** (default): logs every tool call, signs a decision receipt, allows everything through
30
- - **Enforce mode**: applies policy rules block, rate-limit, or gate by trust tier
32
+ - **Shadow mode** (default): logs every tool call and allows everything through
33
+ - **Enforce mode**: applies per-tool policy rules such as `block`, `rate_limit`, and `min_tier`
34
+ - **Optional local signing**: when signing is configured, emits an Ed25519-signed receipt alongside the structured log
31
35
 
32
36
  All other MCP messages (`initialize`, `tools/list`, notifications) pass through transparently.
33
37
 
34
- ## Key Features
35
-
36
- ### Trust-Tier Gating
37
-
38
- Agents present signed manifests. protect-mcp evaluates them into trust tiers and gates tool access accordingly:
39
-
40
- | Tier | Meaning | How Assigned |
41
- |------|---------|--------------|
42
- | `unknown` | No manifest, or invalid signature | Default |
43
- | `signed-known` | Valid signed manifest | Automatic |
44
- | `evidenced` | Manifest + sufficient evidence history | Automatic |
45
- | `privileged` | Operator-granted elevated trust | Manual override |
46
-
47
- Policy example — require `signed-known` for destructive tools:
48
-
49
- ```json
50
- {
51
- "default_tier": "unknown",
52
- "tools": {
53
- "delete_user": { "min_tier": "signed-known", "rate_limit": "5/hour" },
54
- "read_file": { "require": "any" },
55
- "*": { "rate_limit": "100/hour" }
56
- }
57
- }
58
- ```
59
-
60
- ### Credential Vault
61
-
62
- Agents never see raw API keys. Credentials are resolved from environment variables at call time and injected transparently:
63
-
64
- ```json
65
- {
66
- "credentials": {
67
- "stripe_api": {
68
- "inject": "header",
69
- "name": "Authorization",
70
- "value_env": "STRIPE_SECRET_KEY"
71
- },
72
- "github_token": {
73
- "inject": "header",
74
- "name": "Authorization",
75
- "value_env": "GITHUB_TOKEN"
76
- }
77
- }
78
- }
79
- ```
80
-
81
- Decision logs reference credential labels (`stripe_api`), never values.
82
-
83
- ### Signed Decision Receipts
84
-
85
- Every tool call produces an Ed25519-signed v2 artifact — independently verifiable, no trust required:
86
-
87
- ```
88
- [PROTECT_MCP_RECEIPT] {"v":2,"type":"decision_receipt","algorithm":"ed25519","kid":"kPrK...","issuer":"sb:protect","issued_at":"2026-03-21T10:00:00Z","payload":{"decision":"allow","tool":"read_file","tier":"signed-known","policy_digest":"a1b2c3d4","scope":"default","mode":"shadow"},"signature":"a1b2c3..."}
89
- ```
90
-
91
- Verify with the CLI: `npx @veritasacta/verify receipt.json`
92
- Verify in browser: [scopeblind.com/verify](https://scopeblind.com/verify)
93
-
94
- ### Bring Your Own Policy Engine (BYOPE)
95
-
96
- Plug in OPA, Cerbos, or any HTTP policy endpoint:
97
-
98
- ```json
99
- {
100
- "policy_engine": "external",
101
- "external": {
102
- "endpoint": "http://localhost:8181/v1/data/mcp/allow",
103
- "format": "opa",
104
- "timeout_ms": 500,
105
- "fallback": "deny"
106
- }
107
- }
108
- ```
38
+ ## What Ships Today
109
39
 
110
- Supported formats: `opa`, `cerbos`, `generic`. ScopeBlind signs the receipt regardless of who made the decision.
40
+ - **Per-tool policies** block destructive tools, rate-limit expensive ones, and attach minimum-tier requirements
41
+ - **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`
43
+ - **Offline verification** — verify receipts or bundles with `npx @veritasacta/verify`
44
+ - **No account required** — local keys, local policy, local process
111
45
 
112
- ### Audit Bundle Export
46
+ ## Current Capability Boundaries
113
47
 
114
- Export self-contained audit bundles for offline verification or compliance:
48
+ These are important before you roll this out or talk to users:
115
49
 
116
- ```json
117
- {
118
- "format": "scopeblind:audit-bundle",
119
- "version": 1,
120
- "tenant": "my-service",
121
- "receipts": [ ...signed artifacts... ],
122
- "verification": {
123
- "algorithm": "ed25519",
124
- "signing_keys": [ ...JWK keys... ]
125
- }
126
- }
127
- ```
50
+ - **Signing is not automatic on the bare `npx protect-mcp -- ...` path.** That path logs decisions in shadow mode. For local signing, run `npx protect-mcp init` and then start the gateway with the generated policy file.
51
+ - **Tier-aware policy checks are live, but manifest admission is not wired into the default CLI/stdio path.** The CLI defaults sessions to `unknown` unless a host integration calls the admission API programmatically.
52
+ - **Credential config currently validates env-backed credential references and records credential labels in logs/receipts.** Generic per-call injection into arbitrary stdio tools is adapter-specific and is not performed by the default proxy path.
53
+ - **External PDP adapters and audit bundle helpers exist as exported utilities.** They are not yet fully wired into the default CLI path.
128
54
 
129
55
  ## Policy File
130
56
 
@@ -137,11 +63,17 @@ Export self-contained audit bundles for offline verification or compliance:
137
63
  "read_tool": { "require": "any", "rate_limit": "100/hour" },
138
64
  "*": { "rate_limit": "500/hour" }
139
65
  },
140
- "credentials": {
141
- "api_key": { "inject": "header", "name": "Authorization", "value_env": "MY_API_KEY" }
142
- },
143
66
  "signing": {
144
- "key_file": ".protect-mcp-key.json"
67
+ "key_path": "./keys/gateway.json",
68
+ "issuer": "protect-mcp",
69
+ "enabled": true
70
+ },
71
+ "credentials": {
72
+ "internal_api": {
73
+ "inject": "env",
74
+ "name": "INTERNAL_API_KEY",
75
+ "value_env": "INTERNAL_API_KEY"
76
+ }
145
77
  }
146
78
  }
147
79
  ```
@@ -152,7 +84,7 @@ Export self-contained audit bundles for offline verification or compliance:
152
84
  |-------|--------|-------------|
153
85
  | `block` | `true` | Explicitly block this tool |
154
86
  | `require` | `"any"`, `"none"` | Basic access requirement |
155
- | `min_tier` | `"unknown"`, `"signed-known"`, `"evidenced"`, `"privileged"` | Minimum trust tier required |
87
+ | `min_tier` | `"unknown"`, `"signed-known"`, `"evidenced"`, `"privileged"` | Minimum tier required if your host sets admission state |
156
88
  | `rate_limit` | `"N/unit"` | Rate limit (e.g. `"5/hour"`, `"100/day"`) |
157
89
 
158
90
  Tool names match exactly, with `"*"` as a wildcard fallback.
@@ -170,7 +102,7 @@ Add to `claude_desktop_config.json`:
170
102
  "command": "npx",
171
103
  "args": [
172
104
  "-y", "protect-mcp",
173
- "--policy", "/path/to/policy.json",
105
+ "--policy", "/path/to/protect-mcp.json",
174
106
  "--enforce",
175
107
  "--", "node", "my-server.js"
176
108
  ]
@@ -181,7 +113,7 @@ Add to `claude_desktop_config.json`:
181
113
 
182
114
  ### Cursor / VS Code
183
115
 
184
- Same pattern — replace the server command with protect-mcp wrapping it.
116
+ Same pattern — replace the server command with `protect-mcp` wrapping it.
185
117
 
186
118
  ## CLI Options
187
119
 
@@ -193,14 +125,16 @@ Commands:
193
125
  init Generate Ed25519 keypair + config template
194
126
 
195
127
  Options:
196
- --policy <path> Policy JSON file (default: shadow mode, allow-all)
197
- --slug <slug> Service identifier for receipts
128
+ --policy <path> Policy/config JSON file
129
+ --slug <slug> Service identifier for logs/receipts
198
130
  --enforce Enable enforcement mode (default: shadow)
199
131
  --verbose Enable debug logging
200
132
  --help Show help
201
133
  ```
202
134
 
203
- ## Programmatic API
135
+ ## Programmatic Hooks
136
+
137
+ The library also exposes the primitives that are not yet wired into the default CLI path:
204
138
 
205
139
  ```typescript
206
140
  import {
@@ -211,30 +145,60 @@ import {
211
145
  resolveCredential,
212
146
  initSigning,
213
147
  signDecision,
148
+ queryExternalPDP,
149
+ buildDecisionContext,
214
150
  createAuditBundle,
215
151
  } from 'protect-mcp';
216
152
  ```
217
153
 
218
- ## Decision Logs
154
+ Use these if you want to add:
155
+ - manifest admission before a session starts
156
+ - an external PDP (OPA, Cerbos, or a generic HTTP webhook)
157
+ - custom credential-brokered integrations
158
+ - audit bundle export around your own receipt store
219
159
 
220
- Every tool call emits structured JSON to stderr:
160
+ ## Decision Logs and Receipts
221
161
 
222
- ```
223
- [PROTECT_MCP] {"v":2,"tool":"read_file","decision":"allow","tier":"signed-known","reason_code":"policy_allow","policy_digest":"a1b2c3d4","mode":"shadow","timestamp":1710000000}
162
+ Every tool call emits structured JSON to `stderr`:
163
+
164
+ ```json
165
+ [PROTECT_MCP] {"v":2,"tool":"read_file","decision":"allow","reason_code":"observe_mode","policy_digest":"none","mode":"shadow","timestamp":1710000000}
224
166
  ```
225
167
 
226
168
  When signing is configured, a signed receipt follows:
227
169
 
170
+ ```json
171
+ [PROTECT_MCP_RECEIPT] {"v":2,"type":"decision_receipt","algorithm":"ed25519","kid":"...","issuer":"protect-mcp","issued_at":"2026-03-22T00:00:00Z","payload":{"tool":"read_file","decision":"allow","policy_digest":"...","mode":"shadow","request_id":"..."},"signature":"..."}
228
172
  ```
229
- [PROTECT_MCP_RECEIPT] {"v":2,"type":"decision_receipt","algorithm":"ed25519",...,"signature":"..."}
173
+
174
+ Verify with the CLI: `npx @veritasacta/verify receipt.json`
175
+ Verify in browser: [scopeblind.com/verify](https://scopeblind.com/verify)
176
+
177
+ ## Audit Bundles
178
+
179
+ The package exports a helper for self-contained audit bundles:
180
+
181
+ ```json
182
+ {
183
+ "format": "scopeblind:audit-bundle",
184
+ "version": 1,
185
+ "tenant": "my-service",
186
+ "receipts": ["..."],
187
+ "verification": {
188
+ "algorithm": "ed25519",
189
+ "signing_keys": ["..."]
190
+ }
191
+ }
230
192
  ```
231
193
 
194
+ Use `createAuditBundle()` around your own collected signed receipts.
195
+
232
196
  ## Philosophy
233
197
 
234
- - **Shadow first.** See what's happening before you control anything.
235
- - **Receipts, not logs.** Signed, independently verifiable. Not "trust us."
236
- - **Credential isolation.** Agents call tools. They never see API keys.
237
- - **Observe Enforce Audit.** Progressive adoption, not all-or-nothing.
198
+ - **Shadow first.** See what agents are doing before you enforce anything.
199
+ - **Receipts beat dashboard-only logs.** Signed artifacts should be independently verifiable.
200
+ - **Keep the claims tight.** The default CLI path does not yet do everything the long-term architecture will support.
201
+ - **Layer on top of existing auth.** Don't rip out your stack just to add control and evidence.
238
202
 
239
203
  ## License
240
204
 
package/dist/cli.js CHANGED
@@ -3228,7 +3228,7 @@ var ProtectGateway = class {
3228
3228
  // src/cli.ts
3229
3229
  function printHelp() {
3230
3230
  process.stderr.write(`
3231
- protect-mcp \u2014 Signed shadow-mode security gateway for MCP servers
3231
+ protect-mcp \u2014 Shadow-mode security gateway for MCP servers
3232
3232
 
3233
3233
  Usage:
3234
3234
  protect-mcp [options] -- <command> [args...]
@@ -3375,7 +3375,7 @@ async function handleInit(argv) {
3375
3375
  ${bold("protect-mcp initialized!")}
3376
3376
 
3377
3377
  Created:
3378
- ${configPath} Config with shadow mode + tier gating
3378
+ ${configPath} Config with shadow mode + optional local signing
3379
3379
  ${keyPath} Ed25519 signing keypair
3380
3380
 
3381
3381
  ${bold("Next steps:")}
@@ -3389,8 +3389,8 @@ ${bold("Your gateway public key:")}
3389
3389
  ${bold("Key ID (kid):")}
3390
3390
  ${keypair.kid}
3391
3391
 
3392
- Shadow mode is the default \u2014 all tool calls are logged with signed
3393
- receipts, but nothing is blocked. Add --enforce when ready.
3392
+ Shadow mode is the default \u2014 all tool calls are logged and nothing is blocked.
3393
+ Run with the generated policy file if you also want local signed receipts. Add --enforce when ready.
3394
3394
  `);
3395
3395
  }
3396
3396
  function bold(s) {
package/dist/cli.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  // src/cli.ts
10
10
  function printHelp() {
11
11
  process.stderr.write(`
12
- protect-mcp \u2014 Signed shadow-mode security gateway for MCP servers
12
+ protect-mcp \u2014 Shadow-mode security gateway for MCP servers
13
13
 
14
14
  Usage:
15
15
  protect-mcp [options] -- <command> [args...]
@@ -156,7 +156,7 @@ async function handleInit(argv) {
156
156
  ${bold("protect-mcp initialized!")}
157
157
 
158
158
  Created:
159
- ${configPath} Config with shadow mode + tier gating
159
+ ${configPath} Config with shadow mode + optional local signing
160
160
  ${keyPath} Ed25519 signing keypair
161
161
 
162
162
  ${bold("Next steps:")}
@@ -170,8 +170,8 @@ ${bold("Your gateway public key:")}
170
170
  ${bold("Key ID (kid):")}
171
171
  ${keypair.kid}
172
172
 
173
- Shadow mode is the default \u2014 all tool calls are logged with signed
174
- receipts, but nothing is blocked. Add --enforce when ready.
173
+ Shadow mode is the default \u2014 all tool calls are logged and nothing is blocked.
174
+ Run with the generated policy file if you also want local signed receipts. Add --enforce when ready.
175
175
  `);
176
176
  }
177
177
  function bold(s) {
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "protect-mcp",
3
- "version": "0.2.0",
4
- "description": "Security gateway for MCP servers. Tool-level policies, rate limiting, and structured decision logging. Observe-by-default.",
3
+ "version": "0.2.2",
4
+ "description": "Security gateway for MCP servers. Shadow-mode logs by default, per-tool policies, optional local signing, and offline-verifiable receipts.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "module": "dist/index.mjs",
8
8
  "bin": {
9
- "protect-mcp": "./dist/cli.js"
9
+ "protect-mcp": "dist/cli.js"
10
10
  },
11
11
  "exports": {
12
12
  ".": {
@@ -49,7 +49,7 @@
49
49
  "url": "https://github.com/tomjwxf/scopeblind-gateway/issues"
50
50
  },
51
51
  "dependencies": {
52
- "@veritasacta/artifacts": "file:../../artifacts"
52
+ "@veritasacta/artifacts": "^0.2.0"
53
53
  },
54
54
  "optionalDependencies": {
55
55
  "@noble/curves": "^1.8.0",