# The agent door — MCP tools, the machine face, the derivation contract

An agent gets the same door as a person — capture, query, get_event, translate, resolve, subscribe as typed MCP tools, JSON-RPC over POST /mcp, re-dispatched through the same worker fetch with the same key. A door, not a second path.

**Proof, not adjectives.** This build could not verify the gateway's test suite green, so no sentence on this page claims a passing run — the last verified run is recorded in the repository's own CI, not here. The machine face is live on this origin, and npx epcis.dev mcp runs the same server on your bench. The write tools open with a capture key (/get-a-key/).

## The tools, and the two that refuse

| tool | what it does | readOnlyHint | state |
|---|---|---|---|
| capture | POST an EPCIS document through the gateway laws: strip → validate → project-check → stamp → append | false | shipped |
| query | SimpleEventQuery over whatever was captured | true | shipped |
| get_event | one event, by its CBV §8.9 hash identity | true | shipped |
| translate | EPCIS 1.1 / 1.2 / 2.0 XML → 2.0 JSON-LD, with a per-job fidelity report | true | shipped |
| resolve | refuses honestly: returns a typed tool error, never a fabricated resolution — identity resolution lives at id.org.ai (Agent. Human. Thing.) | true | honest refusal |
| subscribe | refuses honestly: a typed tool error, never a silent downgrade to a one-shot pull | false | honest refusal |

## Paste-ready

```json
{ "mcpServers": { "epcis": { "command": "npx", "args": ["epcis.dev", "mcp"] } } }
```

Every tool call dispatches through the same capture pipeline as the REST interface, so validation, refusals and envelope stamping are byte-identical — strip, validate, stamp, append, on your own bench.

## The machine face

/llms.txt (the ledger and summarizer rules) · /agent-classes.json (the single enumeration of agent classes) · /icp.json (this property's derivation contract). Both JSON faces are built from one frozen enumeration — the same module a runtime selector must read. The free zone is compute — translate, validate, hash, capture at $0/event (intent, until published terms bind it). Absent a pre-registered notification channel, every human-gated scope fail-closes (never a silent grant). Who an observer is resolves via id.org.ai — Agent. Human. Thing. No surface here describes the mechanics.
