Metadata-Version: 2.4
Name: honornet-agent-presentation
Version: 0.1.0
Summary: HonorNet agent presentation client (MCP-first) — a protocol shim that mints proofs and presents three-part ADR-009 bundles. It decides nothing (hard rule 3).
Author-email: HonorNet <opensource@honornet.ai>
License: Apache-2.0
Project-URL: Epic, https://github.com/HonorNetAI/HonornetAI/blob/main/docs/strategy/epic-AC-530.md
Project-URL: Tutorial, https://docs.honornet.ai/#/agent-mcp-checkout
Keywords: honornet,mcp,agent,authorization,presentation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# HonorNet agent presentation client (MCP-first)

Make any MCP-capable agent **HonorNet-capable**. This client holds an agent's
credential and its owner's mandate, mints the per-transaction proof of
possession, and presents the three-part [ADR-009](../../docs/adr/ADR-009-three-part-authorization-presentation.md)
bundle to the network. The agent decides *what* the transaction is; this client
presents it and relays the network's decision.

## What this is — and what it is deliberately not

This is a **protocol shim**, not an agent framework. The analog is Visa
publishing an EMV kernel and a reference terminal: the kernel holds the card's
key, mints the cryptogram, and presents it — it decides nothing about what the
cardholder buys. (See [the four-party model](../../docs/four-party-model.md) and
hard rule 3 in [CLAUDE.md](../../CLAUDE.md).)

The tool surface is closed at exactly three tools:

| Tool | Does | Does **not** |
|---|---|---|
| `load_credential` | Hold an issuer-signed identity credential | Issue, mint, or modify a credential |
| `load_mandate` | Hold an owner-signed spend mandate | Mint a mandate or set spending policy |
| `present` | Mint the proof, assemble the bundle, present it, relay the reply | Decide, rank, choose, score, or call a model |

There is no fourth tool. A tool that makes a purchase decision, ranks options,
or calls an LLM is a hard-rule-3 regression and fails CI
([`tests/test_presentation_client_is_not_an_agent_framework.py`](../../tests/test_presentation_client_is_not_an_agent_framework.py)).

## Design

- **Dependency-free.** No `mcp` PyPI package, no LLM SDK, no HTTP library — the
  MCP stdio transport is a small JSON-RPC 2.0 loop, signing comes from
  [`ac-authz`](../../packages/ac-authz) (the in-repo reference of the SDK
  proof/mandate helpers), and transport is stdlib `urllib`. Same
  no-supply-chain discipline as `ac-decision-record` and the AC-620 verifier.
- **Issuer-blind.** A credential is held and presented unchanged in whatever
  recognized format it arrives in; no issuer is named in any code path.
- **Operator-configured endpoint.** Where `present` POSTs is set by the
  operator (env), never chosen by the agent in a tool call — the shim never
  "chooses where to shop."

## Run it

```bash
# Sign proofs with a known agent key (the credential must be issued to it):
export HONORNET_AGENT_SEED=$(python3 -c "import os;print(os.urandom(32).hex())")

# Where to present (omit for a dry run that returns the bundle only):
export HONORNET_PRESENT_ENDPOINT=http://localhost:8000   # /authorize is appended

python3 -m honornet_presentation.server
```

The server then speaks MCP over stdin/stdout. Configure it in an MCP host
(Claude Desktop, an OpenAI-Agents/LangChain MCP client) as a stdio server:

```json
{
  "mcpServers": {
    "honornet": {
      "command": "python3",
      "args": ["-m", "honornet_presentation.server"],
      "env": {
        "HONORNET_AGENT_SEED": "…64 hex chars…",
        "HONORNET_PRESENT_ENDPOINT": "http://localhost:8000"
      }
    }
  }
}
```

| Env var | Meaning |
|---|---|
| `HONORNET_AGENT_SEED` | Hex Ed25519 seed the agent signs proofs with. If unset, an ephemeral key is generated and its public key printed to stderr (demo only). |
| `HONORNET_PRESENT_ENDPOINT` | Where `present` POSTs the bundle (a `/authorize` URL). Unset → `present` is a dry run. |
| `HONORNET_PRESENT_API_KEY` | Optional network caller key (`hn_sandbox_…` / `hn_live_…`) sent as `Authorization: Bearer`. Required by enforced endpoints like the sandbox. Operator-set, never an agent tool argument. |
| `HONORNET_TRUSTED_ISSUER_KEYS` | Optional JSON `{label: issuer_pubkey_hex}` used only for the dry-run self-check. |

## Library use

```python
from honornet_presentation import PresentationClient

client = PresentationClient(agent_seed=seed, endpoint="http://localhost:8000")
client.load_credential(credential)   # issuer-signed, issued to `seed`'s public key
client.load_mandate(mandate)         # owner-signed
result = client.present(transaction) # {bundle, response: <the network's verdict, relayed>}
```

## Tutorial

The end-to-end walkthrough — off-the-shelf MCP agent → sandbox checkout — is
[`docs/tutorials/agent-mcp-checkout.md`](../../docs/tutorials/agent-mcp-checkout.md).
