@cubiczan/chp-mcp
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
One-command MCP install for **CHP Profile B** spend / capital gates and
**tool-approval receipts** (an allowlist is not authorization), plus a
**structured deny ledger** and receipt-gated finance tools.
Wraps @cubiczan/chp so Cursor,
Claude Code, or any MCP client can call evaluate_spend_gate without vendoring
protocol code. Engine digests match the normative golden vectors
(**Profile B 30/30**).
How the pieces fit
For AGENTS.md + skills + Profile A decision_gate / decision_adversary, use
agent-conductor instead.
Install
Cursor / Claude Desktop
Claude Code
Tools
| Tool | Maps to | Purpose |
|------|---------|---------|
| evaluate_spend_gate | evaluateGate | LOCKED / HITL_REQUIRED / BLOCKED + claims + content hash. BLOCKED is also a ledgered policy_deny. |
| approve_spend | approveHuman | Human lock when HITL_REQUIRED (cannot override hard fails). Optional tool + bound_args mint a signed receipt. |
| evaluate_tool_approval | evaluateToolApproval | Allowlist is a pre-filter; host-bound fields merge into args_hash; a receipt is still required |
| issue_approval_receipt | issueApprovalReceipt | Human allow/deny → HMAC-signed receipt + decision log |
| authorize_tool_call | authorizeToolCall | Consume a receipt; deny on drift, host-bound override, expiry, replay, or a bad MAC |
| request_authorization | runtime | Mint a receipt bound to a scoped reference tool, or return HITL / structured deny |
| place_equity_order | reference | Synthetic equity order — scope trading:equities:place, receipt required |
| wire_treasury_transfer | reference | Synthetic treasury wire — scope treasury:wire, always HITL |
| rebalance_portfolio | reference | Synthetic rebalance — scope portfolio:rebalance |
| inspect_audit_ledger | ledger | Trailing CHP-chained deny / authorize / execute entries |
| chp_content_hash | contentHash | Float-aware canonical SHA-256 |
| chp_version | — | Server + protocol versions + deny reason codes + receipt schema |
Example — evaluate a spend
Cookbook — Claude / Cursor tool approval
Managed MCP allowlists (Cursor mcpServers, Claude Desktop, Claude Code)
only answer *“is this tool name installed?”*. They do not bind tenant,
arguments, risk, or a human decision. This server treats that gap as a
hard deny unless a signed **approval receipt** still matches the call
that is about to run.
Receipts are HMAC-SHA256 over CHP canonical JSON
(the same payload discipline as Profile B contentHash / audit-ledger
sig). The MAC covers:
| Field | Role |
|-------|------|
| actor | Human who allowed or denied |
| tool | Concrete tool name (no *) |
| resource | Tenant / resource binding (no *) |
| args_hash | contentHash(host ∪ model arguments, { floatAware: true }) |
| policy_version | Policy the human saw |
| risk | Policy risk for that tool |
| issued_at / expiry | Lifetime |
| decision | allow or deny |
| nonce | Single-use; replay denies |
| signature | HMAC-SHA256 hex |
Set CHP_RECEIPT_KEY (or AUDIT_LEDGER_KEY) in the MCP server env.
Without it the process falls back to a documented insecure default —
fine for the local cookbook, not for production.
Example policy: examples/tool-approval-policy.json.
stripe.create_charge is **on the allowlist** and still cannot run
without a receipt bound to acct_live_acme and the exact charge args.
Host-injected tenant/index bindings use
examples/host-injected-policy.json
(see the host-injected args cookbook below).
1. Allowlist alone — denied
Claude/Cursor has stripe.create_charge enabled. That is not a grant.
Result: RECEIPT_REQUIRED, deny_code: "allowlist_is_not_authorization".
Calling authorize_tool_call with the same payload and **no receipt**
returns DENIED / allowlist_is_not_authorization.
2. Human allow — then authorize
The response includes receipt (take the whole object) and