# Check an agent action over MCP (Python)

This example calls HANRIA's free tools at `https://check.hanria.ai/mcp` with the official Python MCP SDK. It lists
the server's tools, checks the mandate once with `validate_mandate`, then checks one action against it with
`check_action` and prints the decision.

A mandate is the operator's rule set. An action is what the agent wants to do. The decision is `permit`, `deny` or
`escalate`, with the clause that decided it. An `error` outcome means the input did not validate; treat it as deny.
Decisions are advisory: the calling agent or its operator decides what to do with them.

## Run it

Python 3.12 or later (the lock is built for 3.12; tested on 3.12 and 3.14).

```sh
mkdir hanria-mcp-python && cd hanria-mcp-python
curl -fsSO https://hanria.ai/examples/mcp-python/check_action_example.py
curl -fsSO https://hanria.ai/examples/mcp-python/requirements.lock
python3 -m venv .venv
. .venv/bin/activate
pip install --require-hashes -r requirements.lock
python check_action_example.py
```

Expected output (the example mandate permits file actions):

```json
{
  "schema_version": "0.1-draft",
  "outcome": "permit",
  "reason": "clause 'permit-file' applies",
  "mandate_ref": "minimal-permit",
  "clause": "permit-file",
  "action_digest": "f6044fb2f66d8bc4deba7619d4e507e84344533c6bc7e6bcb6b4f1184168b875",
  "receipt": {
    "type": "hanria-receipt-v1",
    "kid": "...",
    "outcome": "permit",
    "action_digest": "f6044fb2f66d8bc4deba7619d4e507e84344533c6bc7e6bcb6b4f1184168b875",
    "mandate_digest": "...",
    "issued_at": "...",
    "not_after": "...",
    "mandate_ref": "minimal-permit",
    "clause": "permit-file",
    "signature": "..."
  }
}
```

The `receipt` is signed with Ed25519. Anyone holding the mandate and the action can check what the service answered,
without asking HANRIA: https://hanria.ai/examples/receipts/README.md. It shows what the check answered, not that the
action was performed.

The exit status is 0 for permit, deny or escalate and 1 for an error outcome or a failed connection.

## Use your own mandate

Replace `MANDATE` and `ACTION` in `check_action_example.py`. Their JSON schemas are in the tool's `inputSchema`,
returned by `tools/list`, and described in https://hanria.ai/llms.txt.

## Data handling

Requests are evaluated in memory and not stored; only daily counts are kept. See https://check.hanria.ai/privacy.
Do not send secrets, personal data or confidential policies. The unchanged example counts as an example call, not
as real use; see https://check.hanria.ai/methodology.

`requirements.txt` pins `mcp==2.2.0`; `requirements.lock` pins every dependency with hashes.
