protect-mcp 0.5.0 → 0.5.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,62 +1,127 @@
1
1
  # protect-mcp
2
2
 
3
- Security gateway for MCP servers. Shadow-mode logs by default, per-tool policies, optional local Ed25519 receipts, and verification-friendly audit output.
3
+ Enterprise security gateway for MCP servers and Claude Code hooks. Signed receipts, Cedar policies, and swarm-aware audit trails.
4
4
 
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.
5
+ ## Quick Start Claude Code
6
6
 
7
- ## Quick Start
7
+ Two commands. Every tool call is receipted.
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
10
+ # 1. Generate hooks, keys, Cedar policy, and /verify-receipt skill
11
+ npx protect-mcp init-hooks
12
12
 
13
- # Shadow mode log every tool call, enforce nothing
14
- npx protect-mcp -- node my-server.js
13
+ # 2. Start the hook server
14
+ npx protect-mcp serve
15
+ ```
15
16
 
16
- # Generate keys + config template for local signing
17
- npx protect-mcp init
17
+ Open Claude Code in the same project. Every tool call is now intercepted, evaluated, and signed.
18
18
 
19
- # Shadow mode with local signing enabled
20
- npx protect-mcp --policy protect-mcp.json -- node my-server.js
19
+ ### What `init-hooks` creates
21
20
 
22
- # Enforce mode
23
- npx protect-mcp --policy protect-mcp.json --enforce -- node my-server.js
21
+ | File | Purpose |
22
+ |------|---------|
23
+ | `.claude/settings.json` | Hook config (PreToolUse, PostToolUse, + 9 lifecycle events) |
24
+ | `keys/gateway.json` | Ed25519 signing keypair (auto-gitignored) |
25
+ | `policies/agent.cedar` | Starter Cedar policy — customize to your needs |
26
+ | `protect-mcp.json` | JSON policy with signing + rate limits |
27
+ | `.claude/skills/verify-receipt/SKILL.md` | `/verify-receipt` skill for Claude Code |
24
28
 
25
- # Export an offline-verifiable audit bundle
26
- npx protect-mcp bundle --output audit.json
29
+ ### Architecture
30
+
31
+ ```
32
+ Claude Code → POST /hook → protect-mcp (Cedar + sign) → response
33
+
34
+ .protect-mcp-log.jsonl
35
+ .protect-mcp-receipts.jsonl
27
36
  ```
28
37
 
29
- ## What It Does
38
+ - **PreToolUse**: synchronous Cedar policy check → deny blocks the tool
39
+ - **PostToolUse**: async receipt signing → zero latency impact
40
+ - **deny is architecturally final** — it cannot be overridden by the model or other hooks
41
+
42
+ ### Endpoints
43
+
44
+ | Method | Path | Description |
45
+ |--------|------|-------------|
46
+ | POST | `/hook` | Claude Code hook endpoint |
47
+ | GET | `/health` | Server status, policy info, signer info |
48
+ | GET | `/receipts` | Recent signed receipts |
49
+ | GET | `/receipts/latest` | Most recent receipt |
50
+ | GET | `/suggestions` | Auto-generated Cedar policy fix suggestions |
51
+ | GET | `/alerts` | Config tamper detection alerts |
30
52
 
31
- protect-mcp sits between your MCP client and server as a stdio proxy:
53
+ ### Verify receipts
32
54
 
55
+ ```bash
56
+ # Inside Claude Code:
57
+ /verify-receipt
58
+
59
+ # From terminal:
60
+ curl http://127.0.0.1:9377/receipts/latest | jq .
61
+ npx protect-mcp receipts
62
+
63
+ # Check policy suggestions:
64
+ curl http://127.0.0.1:9377/suggestions | jq .
33
65
  ```
34
- MCP Client ←stdin/stdout→ protect-mcp ←stdin/stdout→ your MCP server
66
+
67
+ ## Quick Start — MCP Server Wrapper
68
+
69
+ Wrap any stdio MCP server as a transparent proxy:
70
+
71
+ ```bash
72
+ # Shadow mode — log every tool call, enforce nothing
73
+ npx protect-mcp -- node my-server.js
74
+
75
+ # Enforce mode with policy
76
+ npx protect-mcp --policy protect-mcp.json --enforce -- node my-server.js
77
+
78
+ # Generate keys + config template
79
+ npx protect-mcp init
35
80
  ```
36
81
 
37
- It intercepts `tools/call` JSON-RPC requests and:
38
- - **Shadow mode** (default): logs every tool call and allows everything through
39
- - **Enforce mode**: applies per-tool policy rules such as `block`, `rate_limit`, and `min_tier`
40
- - **Optional local signing**: when signing is configured, emits an Ed25519-signed receipt alongside the structured log
82
+ ## How It Works
83
+
84
+ protect-mcp evaluates every tool call against a policy (JSON, Cedar, or external PDP), signs the decision as an Ed25519 receipt, and logs the result.
85
+
86
+ **Two integration modes:**
41
87
 
42
- All other MCP messages (`initialize`, `tools/list`, notifications) pass through transparently.
88
+ | Mode | Transport | Use Case |
89
+ |------|-----------|----------|
90
+ | Hook Server | HTTP (`npx protect-mcp serve`) | Claude Code, agent swarms |
91
+ | Stdio Proxy | stdin/stdout (`npx protect-mcp -- ...`) | Claude Desktop, Cursor, any MCP client |
43
92
 
44
- ## What Ships Today
93
+ **Three policy engines:**
45
94
 
46
- - **Per-tool policies** block destructive tools, rate-limit expensive ones, and attach minimum-tier requirements
47
- - **Structured decision logs** — every decision is emitted to `stderr` with `[PROTECT_MCP]`
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`
49
- - **Offline verification** verify receipts or bundles with `npx @veritasacta/verify`
50
- - **No account required** local keys, local policy, local process
95
+ | Engine | Config | Notes |
96
+ |--------|--------|-------|
97
+ | JSON | `--policy policy.json` | Simple per-tool rules |
98
+ | Cedar | `--cedar ./policies/` | Local WASM evaluation via `@cedar-policy/cedar-wasm` |
99
+ | External PDP | `policy_engine: "external"` | OPA, Cerbos, or any HTTP PDP |
51
100
 
52
- ## Current Capability Boundaries
101
+ ## Swarm Tracking
53
102
 
54
- These are important before you roll this out or talk to users:
103
+ In multi-agent sessions, protect-mcp automatically tracks the swarm topology.
55
104
 
56
- - **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.
57
- - **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.
58
- - **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.
59
- - **External PDP adapters and audit bundle helpers exist as exported utilities.** They are not yet fully wired into the default CLI path.
105
+ **11 hook events handled:**
106
+
107
+ | Event | Type | Description |
108
+ |-------|------|-------------|
109
+ | `PreToolUse` | Sync | Cedar/policy evaluation before tool execution |
110
+ | `PostToolUse` | Async | Receipt signing after tool execution |
111
+ | `SubagentStart` / `SubagentStop` | Lifecycle | Worker agent spawn/completion |
112
+ | `TaskCreated` / `TaskCompleted` | Lifecycle | Coordinator task assignment |
113
+ | `SessionStart` / `SessionEnd` | Lifecycle | Session lifecycle with sandbox detection |
114
+ | `TeammateIdle` | Lifecycle | Agent utilization monitoring |
115
+ | `ConfigChange` | Security | Tamper detection for `.claude/settings.json` |
116
+ | `Stop` | Lifecycle | Finalization + policy suggestion summary |
117
+
118
+ Each receipt includes:
119
+ - `swarm.agent_id`, `swarm.agent_type`, `swarm.team_name`
120
+ - `timing.tool_duration_ms`, `timing.hook_latency_ms`
121
+ - `payload_digest` (SHA-256 hash for payloads >1KB)
122
+ - `deny_iteration` (retry count after denial)
123
+ - `sandbox_state` (enabled/disabled/unavailable)
124
+ - OpenTelemetry `otel_trace_id` and `otel_span_id`
60
125
 
61
126
  ## Policy File
62
127
 
@@ -73,34 +138,50 @@ These are important before you roll this out or talk to users:
73
138
  "key_path": "./keys/gateway.json",
74
139
  "issuer": "protect-mcp",
75
140
  "enabled": true
76
- },
77
- "credentials": {
78
- "internal_api": {
79
- "inject": "env",
80
- "name": "INTERNAL_API_KEY",
81
- "value_env": "INTERNAL_API_KEY"
82
- }
83
141
  }
84
142
  }
85
143
  ```
86
144
 
87
- ### Policy Rules
145
+ ### Cedar Policies
146
+
147
+ Cedar deny decisions are **authoritative** — they cannot be overridden.
148
+
149
+ ```cedar
150
+ // Allow read-only tools
151
+ permit(
152
+ principal,
153
+ action == Action::"MCP::Tool::call",
154
+ resource == Tool::"Read"
155
+ );
156
+
157
+ // Block destructive tools
158
+ forbid(
159
+ principal,
160
+ action == Action::"MCP::Tool::call",
161
+ resource == Tool::"delete_file"
162
+ );
163
+ ```
164
+
165
+ When a tool is denied, protect-mcp auto-suggests the minimal Cedar `permit()` rule via `GET /suggestions`.
166
+
167
+ ## CVE-Anchored Policy Packs
88
168
 
89
- | Field | Values | Description |
90
- |-------|--------|-------------|
91
- | `block` | `true` | Explicitly block this tool |
92
- | `require` | `"any"`, `"none"` | Basic access requirement |
93
- | `min_tier` | `"unknown"`, `"signed-known"`, `"evidenced"`, `"privileged"` | Minimum tier required if your host sets admission state |
94
- | `rate_limit` | `"N/unit"` | Rate limit (e.g. `"5/hour"`, `"100/day"`) |
169
+ Each prevents a real attack:
170
+
171
+ | Policy | Incident | OWASP |
172
+ |--------|----------|-------|
173
+ | `clinejection.json` | CVE-2025-6514: MCP OAuth proxy hijack (437K environments) | A01, A03 |
174
+ | `terraform-destroy.json` | Autonomous Terraform agent destroys production | A05, A06 |
175
+ | `github-mcp-hijack.json` | Prompt injection via crafted GitHub issue | A01, A02, A03 |
176
+ | `data-exfiltration.json` | Agent data theft via outbound tool abuse | A02, A04 |
177
+ | `financial-safe.json` | Unauthorized financial transaction | A05, A06 |
95
178
 
96
- Tool names match exactly, with `"*"` as a wildcard fallback.
179
+ Cedar equivalents available in `policies/cedar/`.
97
180
 
98
181
  ## MCP Client Configuration
99
182
 
100
183
  ### Claude Desktop
101
184
 
102
- Add to `claude_desktop_config.json`:
103
-
104
185
  ```json
105
186
  {
106
187
  "mcpServers": {
@@ -121,146 +202,56 @@ Add to `claude_desktop_config.json`:
121
202
 
122
203
  Same pattern — replace the server command with `protect-mcp` wrapping it.
123
204
 
124
- ## CLI Options
205
+ ## CLI Commands
125
206
 
126
207
  ```
127
- protect-mcp [options] -- <command> [args...]
128
- protect-mcp init
129
-
130
208
  Commands:
209
+ serve Start HTTP hook server for Claude Code (port 9377)
210
+ init-hooks Generate Claude Code hook config + skill + sample Cedar policy
211
+ quickstart Zero-config onboarding: init + demo + show receipts
131
212
  init Generate Ed25519 keypair + config template
132
- status Show decision stats and local passport identity
133
- digest Generate a local human-readable summary
213
+ demo Start a demo server wrapped with protect-mcp
214
+ doctor Check your setup: keys, policies, verifier, connectivity
215
+ trace <id> Visualize the receipt DAG from a given receipt_id
216
+ status Show tool call statistics from the decision log
217
+ digest Generate a human-readable summary of agent activity
134
218
  receipts Show recent persisted signed receipts
135
219
  bundle Export an offline-verifiable audit bundle
220
+ simulate Dry-run a policy against recorded tool calls
221
+ report Generate a compliance report from an audit bundle
136
222
 
137
223
  Options:
138
224
  --policy <path> Policy/config JSON file
139
- --slug <slug> Service identifier for logs/receipts
225
+ --cedar <dir> Cedar policy directory
140
226
  --enforce Enable enforcement mode (default: shadow)
227
+ --port <port> HTTP server port (default: 9377 for serve)
141
228
  --verbose Enable debug logging
142
- --help Show help
143
- ```
144
-
145
- ## Programmatic Hooks
146
-
147
- The library also exposes the primitives that are not yet wired into the default CLI path:
148
-
149
- ```typescript
150
- import {
151
- ProtectGateway,
152
- loadPolicy,
153
- evaluateTier,
154
- meetsMinTier,
155
- resolveCredential,
156
- initSigning,
157
- signDecision,
158
- queryExternalPDP,
159
- buildDecisionContext,
160
- createAuditBundle,
161
- } from 'protect-mcp';
162
229
  ```
163
230
 
164
- Use these if you want to add:
165
- - manifest admission before a session starts
166
- - an external PDP (OPA, Cerbos, or a generic HTTP webhook)
167
- - custom credential-brokered integrations
168
- - audit bundle export around your own receipt store
169
-
170
- ## Decision Logs and Receipts
231
+ ## Decision Logs
171
232
 
172
233
  Every tool call emits structured JSON to `stderr`:
173
234
 
174
235
  ```json
175
- [PROTECT_MCP] {"v":2,"tool":"read_file","decision":"allow","reason_code":"observe_mode","policy_digest":"none","mode":"shadow","timestamp":1710000000}
176
- ```
177
-
178
- When signing is configured, a signed receipt follows:
179
-
180
- ```json
181
- [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":"..."}
236
+ [PROTECT_MCP] {"v":2,"tool":"read_file","decision":"allow","reason_code":"cedar_allow","policy_digest":"a1b2c3...","mode":"enforce","hook_event":"PreToolUse","timing":{"hook_latency_ms":1},"otel_trace_id":"..."}
182
237
  ```
183
238
 
184
- Verify with the CLI: `npx @veritasacta/verify receipt.json`
185
- Verify in browser: [scopeblind.com/verify](https://scopeblind.com/verify)
239
+ When signing is configured, a signed receipt is persisted to `.protect-mcp-receipts.jsonl`.
186
240
 
187
241
  ## Audit Bundles
188
242
 
189
- The package exports a helper for self-contained audit bundles:
190
-
191
- ```json
192
- {
193
- "format": "scopeblind:audit-bundle",
194
- "version": 1,
195
- "tenant": "my-service",
196
- "receipts": ["..."],
197
- "verification": {
198
- "algorithm": "ed25519",
199
- "signing_keys": ["..."]
200
- }
201
- }
202
- ```
203
-
204
- Use `createAuditBundle()` around your own collected signed receipts.
205
-
206
- ## Philosophy
207
-
208
- - **Shadow first.** See what agents are doing before you enforce anything.
209
- - **Receipts beat dashboard-only logs.** Signed artifacts should be independently verifiable.
210
- - **Keep the claims tight.** The default CLI path does not yet do everything the long-term architecture will support.
211
- - **Layer on top of existing auth.** Don't rip out your stack just to add control and evidence.
212
-
213
- ## Incident-Anchored Policy Packs
214
-
215
- Ship with protect-mcp — each prevents a real attack:
216
-
217
- | Policy | Incident | OWASP Categories |
218
- |--------|----------|-----------------|
219
- | `clinejection.json` | CVE-2025-6514: MCP OAuth proxy hijack (437K environments) | A01, A03 |
220
- | `terraform-destroy.json` | Autonomous Terraform agent destroys production | A05, A06 |
221
- | `github-mcp-hijack.json` | Prompt injection via crafted GitHub issue | A01, A02, A03 |
222
- | `data-exfiltration.json` | Agent data theft via outbound tool abuse | A02, A04 |
223
- | `financial-safe.json` | Unauthorized financial transaction | A05, A06 |
224
-
225
- Cedar-native policies are also available in `policies/cedar/`:
226
-
227
- | Policy | Purpose |
228
- |--------|---------|
229
- | `clinejection.cedar` | Cedar equivalent of the clinejection JSON policy |
230
- | `terraform-destroy.cedar` | Cedar equivalent of the terraform-destroy JSON policy |
231
- | `spending-authority.cedar` | Spending authority controls — caps per-tool transaction amounts and requires elevated tiers for high-value operations |
232
-
233
243
  ```bash
234
- # JSON policy
235
- npx protect-mcp --policy node_modules/protect-mcp/policies/clinejection.json -- node server.js
236
-
237
- # Cedar policy (requires @cedar-policy/cedar-wasm)
238
- npx protect-mcp --policy node_modules/protect-mcp/policies/cedar/spending-authority.cedar --enforce -- node server.js
244
+ npx protect-mcp bundle --output audit.json
239
245
  ```
240
246
 
241
- Full OWASP Agentic Top 10 mapping: [scopeblind.com/docs/owasp](https://scopeblind.com/docs/owasp)
242
-
243
- ## BYOPE: External Policy Engines
244
-
245
- Supports OPA, Cerbos, Cedar (AWS AgentCore), and generic HTTP endpoints:
246
-
247
- ```json
248
- {
249
- "policy_engine": "hybrid",
250
- "external": {
251
- "endpoint": "http://localhost:8181/v1/data/mcp/allow",
252
- "format": "cedar",
253
- "timeout_ms": 200,
254
- "fallback": "deny"
255
- }
256
- }
257
- ```
247
+ Self-contained offline-verifiable bundle with receipts + signing keys. Verify with `npx @veritasacta/verify`.
258
248
 
259
249
  ## Standards & IP
260
250
 
261
251
  - **IETF Internet-Draft**: [draft-farley-acta-signed-receipts-00](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/) — Signed Decision Receipts for Machine-to-Machine Access Control
262
252
  - **Patent Status**: 4 Australian provisional patents pending (2025-2026) covering decision receipts with configurable disclosure, tool-calling gateway, agent manifests, and portable identity
263
253
  - **Verification**: MIT-licensed — `npx @veritasacta/verify --self-test`
254
+ - **Microsoft AGT Integration**: [PR #667](https://github.com/microsoft/agent-governance-toolkit/pull/667) — Cedar policy bridge for Agent Governance Toolkit
264
255
 
265
256
  ## License
266
257
 
@@ -7,7 +7,7 @@ import {
7
7
  parseRateLimit,
8
8
  signDecision,
9
9
  startStatusServer
10
- } from "./chunk-V52W3XIN.mjs";
10
+ } from "./chunk-N4F76LTC.mjs";
11
11
 
12
12
  // src/evidence-store.ts
13
13
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -232,7 +232,7 @@ function buildEntities(req) {
232
232
  }
233
233
  ];
234
234
  }
235
- async function evaluateCedar(policySet, req) {
235
+ async function evaluateCedar(policySet, req, schema) {
236
236
  const available = await ensureCedarWasm();
237
237
  if (!available) {
238
238
  return {
@@ -243,16 +243,21 @@ async function evaluateCedar(policySet, req) {
243
243
  }
244
244
  try {
245
245
  const agentId = req.agentId || req.tier;
246
+ const context = {
247
+ tier: req.tier,
248
+ ...req.context || {}
249
+ };
250
+ if (req.toolInput && Object.keys(req.toolInput).length > 0) {
251
+ context.input = req.toolInput;
252
+ }
246
253
  const authRequest = {
247
254
  principal: { type: "Agent", id: agentId },
248
255
  action: { type: "Action", id: "MCP::Tool::call" },
249
256
  resource: { type: "Tool", id: req.tool },
250
- context: {
251
- tier: req.tier,
252
- ...req.context || {}
253
- }
257
+ context
254
258
  };
255
259
  const entities = buildEntities(req);
260
+ const cedarSchema = schema?.schemaJson ?? null;
256
261
  let result;
257
262
  if (typeof cedarWasm.isAuthorized === "function") {
258
263
  result = cedarWasm.isAuthorized({
@@ -262,8 +267,7 @@ async function evaluateCedar(policySet, req) {
262
267
  action: authRequest.action,
263
268
  resource: authRequest.resource,
264
269
  context: authRequest.context,
265
- schema: null
266
- // No schema enforcement — Cedar still evaluates correctly
270
+ schema: cedarSchema
267
271
  });
268
272
  } else if (typeof cedarWasm.checkAuthorization === "function") {
269
273
  result = cedarWasm.checkAuthorization(
@@ -281,7 +285,7 @@ async function evaluateCedar(policySet, req) {
281
285
  action: authRequest.action,
282
286
  resource: authRequest.resource,
283
287
  context: authRequest.context,
284
- schema: null
288
+ schema: cedarSchema
285
289
  });
286
290
  } else {
287
291
  return {
@@ -11,7 +11,7 @@ import {
11
11
  loadPolicy,
12
12
  parseRateLimit,
13
13
  signDecision
14
- } from "./chunk-V52W3XIN.mjs";
14
+ } from "./chunk-N4F76LTC.mjs";
15
15
 
16
16
  // src/hook-server.ts
17
17
  import { createServer } from "http";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  meetsMinTier
3
- } from "./chunk-IUFFDQYZ.mjs";
3
+ } from "./chunk-IWDR5WU3.mjs";
4
4
  import {
5
5
  checkRateLimit,
6
6
  getToolPolicy,
7
7
  parseRateLimit
8
- } from "./chunk-V52W3XIN.mjs";
8
+ } from "./chunk-N4F76LTC.mjs";
9
9
 
10
10
  // src/simulate.ts
11
11
  import { readFileSync } from "fs";
package/dist/cli.js CHANGED
@@ -682,7 +682,7 @@ function buildEntities(req) {
682
682
  }
683
683
  ];
684
684
  }
685
- async function evaluateCedar(policySet, req) {
685
+ async function evaluateCedar(policySet, req, schema) {
686
686
  const available = await ensureCedarWasm();
687
687
  if (!available) {
688
688
  return {
@@ -693,16 +693,21 @@ async function evaluateCedar(policySet, req) {
693
693
  }
694
694
  try {
695
695
  const agentId = req.agentId || req.tier;
696
+ const context = {
697
+ tier: req.tier,
698
+ ...req.context || {}
699
+ };
700
+ if (req.toolInput && Object.keys(req.toolInput).length > 0) {
701
+ context.input = req.toolInput;
702
+ }
696
703
  const authRequest = {
697
704
  principal: { type: "Agent", id: agentId },
698
705
  action: { type: "Action", id: "MCP::Tool::call" },
699
706
  resource: { type: "Tool", id: req.tool },
700
- context: {
701
- tier: req.tier,
702
- ...req.context || {}
703
- }
707
+ context
704
708
  };
705
709
  const entities = buildEntities(req);
710
+ const cedarSchema = schema?.schemaJson ?? null;
706
711
  let result;
707
712
  if (typeof cedarWasm.isAuthorized === "function") {
708
713
  result = cedarWasm.isAuthorized({
@@ -712,8 +717,7 @@ async function evaluateCedar(policySet, req) {
712
717
  action: authRequest.action,
713
718
  resource: authRequest.resource,
714
719
  context: authRequest.context,
715
- schema: null
716
- // No schema enforcement — Cedar still evaluates correctly
720
+ schema: cedarSchema
717
721
  });
718
722
  } else if (typeof cedarWasm.checkAuthorization === "function") {
719
723
  result = cedarWasm.checkAuthorization(
@@ -731,7 +735,7 @@ async function evaluateCedar(policySet, req) {
731
735
  action: authRequest.action,
732
736
  resource: authRequest.resource,
733
737
  context: authRequest.context,
734
- schema: null
738
+ schema: cedarSchema
735
739
  });
736
740
  } else {
737
741
  return {
package/dist/cli.mjs CHANGED
@@ -3,17 +3,17 @@ import {
3
3
  formatSimulation,
4
4
  parseLogFile,
5
5
  simulate
6
- } from "./chunk-YKM6W6T7.mjs";
6
+ } from "./chunk-W4U5VNEC.mjs";
7
7
  import {
8
8
  ProtectGateway,
9
9
  validateCredentials
10
- } from "./chunk-IUFFDQYZ.mjs";
10
+ } from "./chunk-IWDR5WU3.mjs";
11
11
  import {
12
12
  initSigning,
13
13
  isCedarAvailable,
14
14
  loadCedarPolicies,
15
15
  loadPolicy
16
- } from "./chunk-V52W3XIN.mjs";
16
+ } from "./chunk-N4F76LTC.mjs";
17
17
  import "./chunk-PQJP2ZCI.mjs";
18
18
 
19
19
  // src/cli.ts
@@ -1282,7 +1282,7 @@ async function main() {
1282
1282
  if (useHttp) {
1283
1283
  const portIdx = args.indexOf("--port");
1284
1284
  const httpPort = portIdx >= 0 && args[portIdx + 1] ? parseInt(args[portIdx + 1]) : 3e3;
1285
- const { startHttpTransport } = await import("./http-transport-GXIXLVJQ.mjs");
1285
+ const { startHttpTransport } = await import("./http-transport-PWCK7JHZ.mjs");
1286
1286
  startHttpTransport({ port: httpPort, config, serverCommand: childCommand });
1287
1287
  return;
1288
1288
  }
@@ -89,7 +89,7 @@ function buildEntities(req) {
89
89
  }
90
90
  ];
91
91
  }
92
- async function evaluateCedar(policySet, req) {
92
+ async function evaluateCedar(policySet, req, schema) {
93
93
  const available = await ensureCedarWasm();
94
94
  if (!available) {
95
95
  return {
@@ -100,16 +100,21 @@ async function evaluateCedar(policySet, req) {
100
100
  }
101
101
  try {
102
102
  const agentId = req.agentId || req.tier;
103
+ const context = {
104
+ tier: req.tier,
105
+ ...req.context || {}
106
+ };
107
+ if (req.toolInput && Object.keys(req.toolInput).length > 0) {
108
+ context.input = req.toolInput;
109
+ }
103
110
  const authRequest = {
104
111
  principal: { type: "Agent", id: agentId },
105
112
  action: { type: "Action", id: "MCP::Tool::call" },
106
113
  resource: { type: "Tool", id: req.tool },
107
- context: {
108
- tier: req.tier,
109
- ...req.context || {}
110
- }
114
+ context
111
115
  };
112
116
  const entities = buildEntities(req);
117
+ const cedarSchema = schema?.schemaJson ?? null;
113
118
  let result;
114
119
  if (typeof cedarWasm.isAuthorized === "function") {
115
120
  result = cedarWasm.isAuthorized({
@@ -119,8 +124,7 @@ async function evaluateCedar(policySet, req) {
119
124
  action: authRequest.action,
120
125
  resource: authRequest.resource,
121
126
  context: authRequest.context,
122
- schema: null
123
- // No schema enforcement — Cedar still evaluates correctly
127
+ schema: cedarSchema
124
128
  });
125
129
  } else if (typeof cedarWasm.checkAuthorization === "function") {
126
130
  result = cedarWasm.checkAuthorization(
@@ -138,7 +142,7 @@ async function evaluateCedar(policySet, req) {
138
142
  action: authRequest.action,
139
143
  resource: authRequest.resource,
140
144
  context: authRequest.context,
141
- schema: null
145
+ schema: cedarSchema
142
146
  });
143
147
  } else {
144
148
  return {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  startHookServer
3
- } from "./chunk-IAJJA5IW.mjs";
4
- import "./chunk-V52W3XIN.mjs";
3
+ } from "./chunk-Q4KOQUKV.mjs";
4
+ import "./chunk-N4F76LTC.mjs";
5
5
  import "./chunk-PQJP2ZCI.mjs";
6
6
  export {
7
7
  startHookServer
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ProtectGateway
3
- } from "./chunk-IUFFDQYZ.mjs";
4
- import "./chunk-V52W3XIN.mjs";
3
+ } from "./chunk-IWDR5WU3.mjs";
4
+ import "./chunk-N4F76LTC.mjs";
5
5
  import "./chunk-PQJP2ZCI.mjs";
6
6
 
7
7
  // src/http-transport.ts