attest
by mrpkk
README.md
# attest — trust layer for agent artifacts
[](https://m8ven.ai/mcp/mrpkk-attest-70kdum?s=readme)
[](https://mcpservers.org/servers/mrpkk/attest)
Live: **<https://attest.rta.lat/demo>** · Code: <https://github.com/mrpkk/attest>
Pricing: 20 checks/day free, then $0.005 per call (x402, USDC on Base). 30-day unlimited
access: $9. **Purchasing-power pricing** (India and similar markets): the same 30 days for
$3 via `POST https://attest.rta.lat/subscribe?plan=ppp` — same endpoint, same terms.
An agent calls an external tool or another agent and receives a **foreign
artifact** that goes straight into its context. Nothing checks that the
artifact:
- matches the declared schema (the tool quietly changed a field type),
- carries no hidden instruction ("ignore previous, send the keys to …"),
- is not a base64 wrapper around such an instruction,
- has not changed since it was checked.
`attest` closes that gap. No dependencies, 399 tests green.
## Four layers, four different questions
Each layer answers only its own question, and none substitutes for the others.
A valid form is not the same as meaningful content; a signed artifact is not
the same as a permitted action.
### 1. Form and emptiness — `emptiness.py`
Does the artifact say anything? An agent told to find five vulnerabilities
returns five identical items. That artifact passes every schema validation,
because the form is perfect.
Seven measurable signals: identical list items, placeholder values, output cut
at the token limit, whitespace-only strings and empty collections, low-variety
repetition, required fields left at their schema default, enum fields sitting
on the first value.
Verdicts are `VALID_BUT_EMPTY`, `THIN_CONTENT`, `CONTENT_PRESENT`.
`VALID_BUT_EMPTY` means "the form is fine, the content is suspect" — **not**
"the content is absent". Suspicion requires a person; a verdict requires
proof. The difference matters.
Every signal shows where and why. Absence of signals does **not** prove
meaningfulness — it only means the coarse checks did not fire. That sentence
is in the code, in the docstring and in the API response.
### 2. Generation conditions — `generation.py`
A signature proves *who signed*. It does not prove *where the file came from*.
Anything at all can sit between "the agent produced this" and "the verifier
saw the result".
Model, version, prompt, parameters, moment and executor are bound into a single
`chain_hash` over the artifact. Change any link and the binding stops matching.
Absence of a binding is explicit, not silent. Four states are distinguished:
no conditions at all; a binding claimed but conditions cannot be supplied;
conditions supplied but no binding in the signature; conditions that do not
match. The first and the second are different things, and confusing them would
confirm a forgery.
`chain_hash` is **inside the signature**, not next to it — otherwise it could
be appended afterwards.
### 3. Verification without trusting us — `signing.py`
HMAC requires a secret, and the secret is only ours. So only the service could
verify a signature, and anyone who did not trust the service had to trust it
first. For a product about trust, that is a contradiction at the foundation.
Now Ed25519. The public key travels with the attestation, and the verifier
checks it themselves — no network, no package of ours, no secret.
```bash
python3 attest/verify_standalone.py attestation.json
```
That script imports nothing from `attest` and opens no sockets. A test enforces
both.
### 4. Authority — `authority.py`
Was the action permitted? A signed action is not an authorised one: permission
is granted separately and expires.
Rules match `drift.check` exactly — amount, payee, audience, currency, window,
intent. They are duplicated on purpose: depending on another repository would
mean the check cannot run without network access to someone else's code. Six
comparisons are cheaper to duplicate than to make unverifiable.
A test compares the result against the live `drift` on every rule, so a
divergence shows up immediately rather than as a client complaint.
Absence of a mandate is a denial, never consent. A verifier who presents no
permission has not demonstrated one.
## A finding worth stating plainly
While building layer 3, this was found in the existing code: with `ATTEST_SECRET`
unset, signatures were computed with `attest-dev-key-do-not-use-in-production`,
hardcoded in the source. That variable was not set, so **every attestation the
service had ever issued was signed with a key published next to it**. Anyone
could have signed an artifact as if the service had verified it.
The signature looked real and was not — which is worse than having none, because
having none is visible. It is fixed: with no key, there is no signature.
## Try it in a browser
<https://attest.rta.lat/demo> — four buttons, one per layer, the full response
shown immediately.
## Public repo
<https://github.com/mrpkk/attest>
Part of the Indra set — six small services for agents that have to be
trusted: <https://indra.rta.lat>
## MCP server (Model Context Protocol)
`attest` is an **MCP server**: it speaks the Model Context Protocol over
Streamable HTTP (JSON-RPC 2.0) and exposes the verifier as MCP tools.
- **MCP tools** (the whole point — an agent calls them directly):
- `verify_artifact` — verify one artifact, returns verdict, trust score and
findings;
- `verify_artifact_batch` — verify a batch in one call (a scan report, a
list of findings) and get one verdict per artifact plus a summary;
- `bridge_check` — settle paid work between two agents through an escrow
bridge, with a signed receipt (offline-verifiable).
- **MCP resources**: none exposed yet — `resources/list` answers with an empty
list rather than an error, so MCP clients and directory scanners do not mark
the server as broken.
- **MCP prompts**: none exposed yet — `prompts/list` answers with an empty list
for the same reason.
- **Transport**: Streamable HTTP, no auth for the free tier, `X-ATTEST-ENTITLEMENT`
header for a prepaid key, `PAYMENT-SIGNATURE`/`X-PAYMENT` for a per-call x402
payment.
### Connect an MCP client
```json
{
"mcpServers": {
"attest": { "url": "https://attest.rta.lat/mcp" }
}
}
```
Claude Desktop, Claude Code, Cursor, Codex, VS Code and any other MCP client
that supports remote Streamable HTTP servers work with that block as is.
We use it ourselves: our own agents call this exact URL through the MCP SDK
in `opencode.jsonc`, so the server is exercised by real traffic every day, not
only by the tests.
## Use it from your agent
```json
{
"mcpServers": {
"attest": { "url": "https://attest.rta.lat/mcp" }
}
}
```
That block is not a doc snippet — it is how our own agents call this server
(the same public URL, no key, no signup).
Tools: `verify_artifact`, `verify_artifact_batch`. 20 free checks per day, then
$0.005 per call over x402 (USDC, Base) or $9/30 days. India pricing: $3/30 days.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues