@cubiczan/chp-mcp
This server exposes CHP Profile B spend/capital gating over MCP: evaluate a proposed action against policy limits, get human HITL approval, and compute canonical content hashes.
evaluate_spend_gate— run a proposed trade/spend action (asset, action, notional, optional confidence/rationale) against a policy (max_notional,daily_cap,hitl_threshold,min_confidence,allowed_actions,per_asset_limits), optionally net ofcommitted_today; returnsLOCKED,HITL_REQUIRED, orBLOCKEDwith claims and a content hash. Hard policy violations cannot be human-overridden.approve_spend— human-in-the-loop approval (byapproveridentity) for proposals that returnedHITL_REQUIRED; cannot approveBLOCKEDhard-rule failures.chp_content_hash— compute the float-aware canonical SHA-256 digest of any JSON value (CHP §3.1), matching Pythonconsensus-hardening-protocoldigests.chp_version— report the MCP server and CHP Profile B protocol versions.All tools are synchronous (
taskSupport: forbidden); inputs are strict (additionalProperties: false).Note: the README describes many more tools (tool-approval receipts, host-bound args, deny ledger, receipt-gated finance tools,
inspect_audit_ledger) that are not present in this schema.
Governs Stripe tool calls such as stripe.create_charge with signed human-approval receipts: the charge args and tenant (acct_live_acme) are hashed into an HMAC receipt, and a Stripe call is denied unless a matching, unexpired, non-replayed receipt exists — an MCP allowlist alone is treated as a deny.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@cubiczan/chp-mcpEvaluate spend gate for a LONG ETH trade with 300 notional."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@cubiczan/chp-mcp
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
MCP client (Cursor / Claude / …)
│ tools/call
▼
┌───────────────────────────┐
│ MCP server (transport) │ ← you are here (@cubiczan/chp-mcp)
│ evaluate_spend_gate │
│ approve_spend │
│ evaluate_tool_approval │ allowlist ≠ authorization
│ issue_approval_receipt │
│ authorize_tool_call │
│ request_authorization │ finance-tool receipt / HITL / deny
│ place_equity_order │ scoped + receipt-gated (synthetic)
│ wire_treasury_transfer │
│ rebalance_portfolio │
│ inspect_audit_ledger │ CHP-signed deny / authorize / execute
│ chp_content_hash │
└─────────────┬─────────────┘
│ depends on
▼
┌───────────────────────────┐
│ Published CHP packages │
│ npm: @cubiczan/chp (Profile B)
│ PyPI: consensus-hardening-protocol (Profile A)
└───────────────────────────┘For AGENTS.md + skills + Profile A decision_gate / decision_adversary, use
agent-conductor instead.
Related MCP server: Datashift MCP Server
Install
npm install -g @cubiczan/chp-mcp
# or one-shot
npx -y @cubiczan/chp-mcpCursor / Claude Desktop
{
"mcpServers": {
"chp": {
"command": "npx",
"args": ["-y", "@cubiczan/chp-mcp"]
}
}
}Claude Code
claude mcp add chp -- npx -y @cubiczan/chp-mcpTools
Tool | Maps to | Purpose |
|
| LOCKED / HITL_REQUIRED / BLOCKED + claims + content hash. |
|
| Human lock when HITL_REQUIRED (cannot override hard fails). Optional |
|
| Allowlist is a pre-filter; host-bound fields merge into |
|
| Human allow/deny → HMAC-signed receipt + decision log |
|
| Consume a receipt; deny on drift, host-bound override, expiry, replay, or a bad MAC |
| runtime | Mint a receipt bound to a scoped reference tool, or return HITL / structured deny |
| reference | Synthetic equity order — scope |
| reference | Synthetic treasury wire — scope |
| reference | Synthetic rebalance — scope |
| ledger | Trailing CHP-chained deny / authorize / execute entries |
|
| Float-aware canonical SHA-256 |
| — | Server + protocol versions + deny reason codes + receipt schema |
Example — evaluate a spend
// tools/call evaluate_spend_gate
{
"action": { "action": "LONG", "asset": "ETH", "notional": 300, "confidence": 0.9 },
"policy": {
"max_notional": 500,
"daily_cap": 2500,
"hitl_threshold": 250,
"min_confidence": 0.55,
"allowed_actions": ["LONG", "SHORT"]
}
}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 |
| Human who allowed or denied |
| Concrete tool name (no |
| Tenant / resource binding (no |
|
|
| Policy the human saw |
| Policy risk for that tool |
| Lifetime |
|
|
| Single-use; replay denies |
| 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).
{
"mcpServers": {
"chp": {
"command": "npx",
"args": ["-y", "@cubiczan/chp-mcp"],
"env": { "CHP_RECEIPT_KEY": "replace-me" }
}
}
}1. Allowlist alone — denied
Claude/Cursor has stripe.create_charge enabled. That is not a grant.
// tools/call evaluate_tool_approval
{
"call": {
"tool": "stripe.create_charge",
"resource": "acct_live_acme",
"arguments": { "amount": 2500, "currency": "usd", "customer": "cus_123" }
},
"policy": { "$ref": "examples/tool-approval-policy.json" }
}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
// tools/call issue_approval_receipt
{
"actor": "cfo@acme.example",
"decision": "allow",
"reason": "invoice INV-104 matches amount",
"ttl_seconds": 120,
"call": { /* same as above */ },
"policy": { /* same as above */ }
}The response includes receipt (take the whole object) and
decision_log (actor, decision, args hash, nonce). Pass that receipt
into authorize_tool_call with the same call. Result: AUTHORIZED.
3. Human deny
Issue with "decision": "deny". The decision is logged. Authorizing
with that receipt returns DENIED / human_denied. A deny receipt
cannot be flipped to allow by editing decision — the MAC breaks.
4. Changed arguments after approval — denied
Approve { "amount": 2500, ... }, then authorize with
{ "amount": 2500000, ... }. Result: DENIED / changed_arguments.
Key order does not matter; the hash is CHP canonical. The original
receipt remains valid for the args that were approved (until expiry or
a successful consume).
5. Expired receipt — denied
Issue with ttl_seconds: 30. After the expiry instant,
authorize_tool_call returns DENIED / expired_receipt. The nonce is
consumed so a clock rewind cannot resurrect it.
6. Replayed receipt — denied
A successful AUTHORIZED consume burns the nonce. Presenting the same
receipt again returns DENIED / replayed_receipt.
7. Ambiguity — denied
These never produce a usable allow receipt:
resource: "*",any,all, or an empty stringmissing
argumentspolicy without a concrete
versionactor / tool wildcards
extra keys on a receipt (strict parse)
Fail-closed: deny_on_ambiguity cannot be turned off.
Cookbook — host-injected args + gateway _meta
Semantic Kernel and other hosts need to pass index, key, and tenant
without letting the model choose them
(SO-style routing).
Putting those fields on the tool schema so the LLM can “decide” is the
bug. An MCP allowlist does not fix it: the tool name can stay
allowlisted while the model swaps index_name to another tenant.
The host (or a gateway in front of this server) injects bound fields. This package hashes host ∪ model arguments into the receipt and denies when the model overrides a host-bound field. The allowlist is still only a pre-filter.
Contract — _meta.cubiczan (no hard dependency)
@cubiczan/governed-mcp-gateway
already injects identity on every tools/call and SSE frame:
{
"_meta": {
"cubiczan": {
"principal": {
"id": "agt_search",
"kind": "agent",
"orgId": "org_acme",
"displayName": "Search Runner"
}
}
}
}This server does not import that package. It reads the same
envelope. Hosts MAY add host_bound next to principal. A trusted
gateway should overwrite _meta.cubiczan so the model cannot self-attest.
{
"_meta": {
"cubiczan": {
"principal": { "id": "agt_search", "kind": "agent", "orgId": "org_acme" },
"host_bound": { "tenant_id": "acme", "index_name": "prod-docs" }
}
}
}Library callers can also pass host_bound on the proposed call
(explicit keys overlay _meta). Policy
examples/host-injected-policy.json
declares host_bound_fields so index_name and tenant_id must be
host-injected and concrete. If tenant_id is declared and omitted,
_meta.cubiczan.principal.orgId may fill it.
model args ──┐
├─ override check ─→ deny host_bound_override
host_bound ──┘ │
▼
merged args → args_hash → receipt MAC
│
allowlist ──── pre-filter only (never a grant)1. Host injects index + tenant — allowlist still denied
The model chose query / top_k. The host chose the index.
// tools/call evaluate_tool_approval
{
"call": {
"tool": "search.azure_ai",
"resource": "tenant:acme",
"arguments": { "query": "Q3 revenue", "top_k": 5 },
"_meta": {
"cubiczan": {
"principal": { "id": "agt_search", "kind": "agent", "orgId": "org_acme" },
"host_bound": { "tenant_id": "acme", "index_name": "prod-docs" }
}
}
},
"policy": { "$ref": "examples/host-injected-policy.json" }
}Result: RECEIPT_REQUIRED, deny_code: "allowlist_is_not_authorization".
args_hash is contentHash of
{ query, top_k, tenant_id, index_name } — not the model object alone.
2. Model changes a host-bound field — denied
Same host _meta, but the model adds "index_name": "other-index".
"arguments": { "query": "Q3 revenue", "top_k": 5, "index_name": "other-index" }evaluate_tool_approval, issue_approval_receipt (decision: "allow"),
and authorize_tool_call all return DENIED /
host_bound_override. Matching the host value is not an override.
3. Human allow — then authorize the merged args
Issue a receipt for the host-injected call. Authorize with the same
arguments and _meta. Result: AUTHORIZED. Change query after
approve → changed_arguments. Change index_name in model args →
host_bound_override. Omit declared host fields → ambiguous.
4. Semantic Kernel / host wiring
Do the routing in the host, not the model: disable auto-invoke, then
inject index/tenant (or put a gateway in front that writes
_meta.cubiczan.host_bound) before evaluate_tool_approval /
authorize_tool_call. Secrets such as API keys belong in the host or
the gateway vault — not in the tool schema the LLM sees.
Cookbook — deny telemetry and receipts
MCP denials are usually a bare error string. That string is gone when the client disconnects. This server treats a refuse as a structured event that must hit a CHP-signed ledger before the caller sees it.
Finance tools (place_equity_order, wire_treasury_transfer,
rebalance_portfolio) are synthetic — no live venue or bank rail — and
use a separate kind: "authorization" receipt bound to tool, scope, and
args hash. That is not the same object as a chp.tool_approval_receipt.
Reason codes
Code | When |
| Hard CHP rule failed ( |
| Receipt |
| Receipt already consumed by a successful execute |
| Tool, scope, or args hash no longer matches the receipt |
| No receipt, or the content hash does not verify |
| Unknown tool, scope mismatch, or incomplete policy |
Signing is the existing Profile B primitives: contentHash on the
receipt / ledger payload, chainHash between ledger rows. Set
CHP_AUDIT_LEDGER to a JSONL path (default ./data/chp-audit.jsonl),
or :memory: for tests.
1. Request a bound receipt
Under the HITL threshold the gate auto-locks and mints a receipt. At or
above it, pass approver (or call approve_spend with tool +
bound_args).
// tools/call request_authorization
{
"tool": "place_equity_order",
"args": {
"symbol": "AAPL",
"side": "BUY",
"quantity": 10,
"notional": 300,
"confidence": 0.9
},
"approver": "cfo@example.com"
}Treasury wires use hitl_threshold: 0. A request without approver
returns HITL_REQUIRED and no receipt — that is the approval gate,
not a weather-API demo.
2. Execute only with that receipt
receipt is optional on the wire so a missing token is a logged
missing_receipt deny, not a schema 400 that never hits the ledger.
// tools/call place_equity_order
{
"symbol": "AAPL",
"side": "BUY",
"quantity": 10,
"notional": 300,
"confidence": 0.9,
"receipt": { "kind": "authorization", "receipt_id": "…", "content_hash": "…" }
}Change notional or quantity after approve → args_changed, and the
ledger has the deny. Call again with the same receipt → replay.
Call with no receipt → missing_receipt. All three are durable.
3. Inspect the chain
// tools/call inspect_audit_ledger
{ "limit": 20 }Each row carries content_hash and sig = chainHash(prev_sig, { seq, ts, event, content_hash }).
chain.ok is false if anyone rewrote history.
Tests
npm testThis Cubiczan mirror may omit GitHub Actions; run the suite locally.
npm test builds, then runs node --test dist/*.test.js (approval
receipts + host-injected bindings) and
node --import tsx --test test/**/*.test.ts (deny ledger). Invariants
covered: an unlogged deny is impossible (ledger failure throws instead
of returning a deny object); changed args after approve deny; a receipt
is required for every gated reference tool; allowlist is not
authorization; host-bound tenant/index cannot be overridden by the
model; receipt args_hash covers host ∪ model args.
Related
Package / repo | Role |
Profile B library (this server’s dependency) | |
Profile A + normative spec | |
Full MCP: contracts, skills, Profile A gates | |
HTTP MCP control plane | |
Codebase health MCP | |
Shared retry / timeout / audit primitives |
Licence
MIT.
Available Tools
4 toolsapprove_spendA
Human-in-the-loop approval for a proposal that returned HITL_REQUIRED. Cannot approve BLOCKED / hard-rule failures (spec §6.3 / §6.5).
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| policy | Yes | ||
| approver | Yes | Human approver identity (email or handle) | |
| committed_today | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the burden of behavioral disclosure. It adds useful constraints: only HITL_REQUIRED proposals are approvable, and BLOCKED / hard-rule failures are not. However, it does not state whether approval executes the spend, what side effects occur, what permissions are required, or what the return behavior is.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The key use condition and hard exclusion are stated immediately and clearly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with four parameters, nested objects, no annotations, and no output schema, this description is too sparse. It does not explain how to construct the action/policy payload, what a successful approval returns, or how to obtain the HITL_REQUIRED proposal in the first place.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25% (just the approver field has a description). The tool description does not explain the action object, policy object, or committed_today semantics. Since schema coverage is low, the description needed to compensate but does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Human-in-the-loop approval') applied to a specific resource ('a proposal that returned HITL_REQUIRED') and explicitly excludes BLOCKED / hard-rule failures. This clearly distinguishes it from evaluative sibling tools like evaluate_spend_gate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool (proposals that returned HITL_REQUIRED) and when not to use it (BLOCKED / hard-rule failures), with spec section references. It does not explicitly name an alternative tool, but the exclusion criteria provide strong situational guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chp_content_hashA
SHA-256 over float-aware canonical JSON (CHP §3.1) — matches Python consensus-hardening-protocol digests for the same object.
| Name | Required | Description | Default |
|---|---|---|---|
| value | No | JSON-serializable value to hash |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the algorithm (SHA-256), the canonicalization method, and the consistency with Python digests. It doesn't mention edge cases or determinism, but for a pure hash function, this is reasonable. A minor gap is the lack of explicit side-effect-free declaration.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that front-loads the core operation (SHA-256 over float-aware canonical JSON) and adds the interoperability detail. Every word earns its place, with no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has one parameter, no output schema, and no annotations. The description fails to specify the return format (e.g., hex string, base64, binary) or error behavior for invalid inputs. An agent cannot be sure how to interpret the result, which is a significant gap for a hash function. Given the simplicity, this should have been included.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides 100% coverage for the single parameter 'value' with the description 'JSON-serializable value to hash'. The tool description adds no additional semantic meaning beyond that, so the baseline of 3 applies. It doesn't clarify format, size limits, or serialization specifics beyond what's in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool computes a SHA-256 hash over float-aware canonical JSON, referencing CHP §3.1 and matching Python consensus-hardening-protocol digests. This specifies the verb (compute hash), resource (canonical JSON), and the exact algorithm, distinguishing it from unrelated sibling tools like chp_version.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for cross-language consistency (matching Python digests) within the CHP protocol. While it doesn't explicitly list when not to use it, there are no similar sibling tools, so the context is sufficient. It could be more explicit about typical use cases, but the purpose is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chp_versionA
Report MCP server and CHP Profile B protocol versions.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description implies a read-only operation via 'Report', but does not explicitly state that no data is modified or that it is safe to call. Since no annotations are provided, the description carries the full burden of transparency and could be more explicit about side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence with no unnecessary words or repetition. It is well-structured and easy to understand.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity of the tool (no parameters, no output schema), the description is complete and sufficient. It fully describes the tool's purpose without leaving any critical gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters in the input schema, so the description adds no parameter-level information. The baseline score of 3 is appropriate as there is nothing to describe.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reports MCP server and CHP Profile B protocol versions, with a specific verb and resource. No ambiguity or missing information.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide any guidance on when to use this tool, such as checking version compatibility before other operations. It simply states what it does without context or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
evaluate_spend_gateA
Run CHP Profile B capital/spend gate on a proposed action. Returns LOCKED, HITL_REQUIRED, or BLOCKED with claims and a content hash. Hard policy violations cannot be overridden by a human.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Proposed trade / spend / mandate action | |
| policy | Yes | Gate policy (limits, HITL threshold, confidence floor) | |
| committed_today | No | Notional already committed today toward daily_cap (default 0) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations were provided, so the description carries the disclosure burden. It does disclose a key behavioral fact: hard policy violations cannot be overridden by a human. However, it does not state whether the tool mutates state, consumes budget/quota, requires authentication, or what happens on error, leaving notable gaps for a policy-evaluation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loads the core action and outcomes, and avoids filler. Every clause adds useful information: the gate type, the possible return states, the presence of claims plus content hash, and the hard-block caveat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description gives enough for basic use but lacks some completeness for a nested-parameter tool with no output schema. It does not explain the distinction between LOCKED and BLOCKED, the shape of the claims, or the meaning of the content hash. The behavioral caveat helps, but the description is not richly complete given the complexity of the inputs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high: the top-level parameters action, policy, and committed_today each have descriptions. The tool description adds no additional parameter semantics beyond the schema, so the baseline 3 is appropriate. Nested fields like asset, notional, max_notional, and hitl_threshold remain self-describing from names but are not elaborated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Run') and names a clear resource ('CHP Profile B capital/spend gate on a proposed action'). It also lists concrete outputs (LOCKED, HITL_REQUIRED, or BLOCKED with claims and a content hash), which clearly distinguishes this from sibling tools like approve_spend and chp_content_hash.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: to evaluate a proposed action against the CHP Profile B spend gate before approval. However, it does not explicitly mention alternatives, exclusions, or how this tool relates to approve_spend, chp_content_hash, or chp_version, so the guidance is not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
approve_spend - First observed
chp_content_hash - First observed
chp_version - First observed
evaluate_spend_gate
TDQS
Scored across 4 tools
Each tool has a clearly distinct role: evaluate_spend_gate runs the policy check, approve_spend performs HITL approval, chp_content_hash computes hashes, and chp_version reports versions. No two tools overlap in purpose or could be easily confused.
The names are consistent snake_case and mostly follow a verb_noun pattern (evaluate_spend_gate, approve_spend). The chp_ prefixed helpers break that pattern slightly, but the prefix clearly groups utility/version operations, so the overall convention remains predictable.
Four tools is well-scoped for a narrow CHP Profile B protocol surface: gate evaluation, human approval, hashing, and versioning. Each tool earns its place without redundancy or bloat.
The core lifecycle is covered: evaluate → approve, with supporting hash and version utilities. A minor gap is the absence of an explicit tool to inspect proposal details, but the described results from evaluate_spend_gate include claims and content hashes, so agents can proceed without major dead ends.
Maintenance
Related MCP Connectors
Human-in-the-loop review and approval for AI agents. Audit trail, approval policies, native MCP.
Read-only BUY / WAIT / AVOID spend gate for paid APIs, MCP endpoints, and x402 routes.
Paid remote MCP for AI Studio Workspace approval gate MCP, structured receipts, audit logs, and revi
Human-in-the-loop for AI agents over MCP: durable approvals with a hosted review page & audit trail
Related MCP Servers
- FlicenseAqualityBmaintenanceGovernance/control plane for MCP-enabled coding-agent workflows with validation, findings, approvals, budgets, and proof bundles.5511-

Datashift MCP Serverofficial
AlicenseNot gradedqualityDmaintenanceEnables AI agents to submit tasks for human or AI review and receive decisions via MCP tools, adding human review checkpoints to workflows.MIT- AlicenseAqualityAmaintenanceAI-powered codebase health analysis — detects dead code, circular dependencies, coupling issues, and architectural drift. 6 MCP tools for Claude Desktop, Cursor, Windsurf, and Slack.663 npmMIT
- FlicenseNot gradedqualityDmaintenanceA code quality analysis server that detects security vulnerabilities, deceptive patterns, incomplete code, and highlights good practices in source code for MCP-compatible clients like Claude Code.3-