tersign
OfficialTersign is an evidence layer for agent commerce, providing a suite of tools to issue, verify, and manage cryptographically signed, hash-chained records for transactions, disclosures, refunds, and disputes.
Issue Signed Receipts: Create x402 offer-receipts (EIP-712) with compliance records for settled payments, optionally counter-signed by the ledger.
Verify Receipts: Authenticate receipt artifacts and optionally enforce an expected signer.
Record Disclosures: Generate counter-signed evidence of AI disclosures, digesting the text locally to protect privacy (e.g., EU AI Act Art. 50).
Verify Compliance Records: Validate compliance record attestations and their digest bindings.
Record Refunds: Link refunds to original receipts in the ledger.
Open Disputes: Start objective disputes with reason codes like not_delivered, wrong_content, or duplicate_charge.
Submit Dispute Evidence: Attach signed evidence to disputes with role-based permissions.
Adjudicate Disputes: Trigger deterministic resolution that may automatically create refund records.
Fetch Dispute Records: Retrieve full dispute details including evidence, verdict, and rationale.
Anchors the Tersign hash-chain head to the Bitcoin blockchain on a six-hourly cron, providing public, immutable timestamping for counter-signed ledger entries.
Uses Cloudflare D1 as an idempotency store for receipt issuance, ensuring duplicate requests do not create duplicate records.
Click on "Install 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., "@tersignverify the receipt for the last transaction"
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.
Tersign is the evidence layer for the agent economy — a neutral, counter-signed, hash-chained ledger for agent commerce. Sellers sign EIP-712 receipts; Tersign chains them per seller and counter-signs every entry. When the dispute comes, the transcript is already sealed.
Venues rotate. The transcript endures.
Verify a Real Entry — Right Now
No account. No API key. This is the genesis receipt, seq 1 on the production chain:
npx tersign verify 0xe5874f1ffe87f0a6dd9eb157730f67b86ee4538b125fe30fcc4e165213dd3fc4ledger: counter-signed OK (seller tersign-first, seq 1 …) VALIDnpx tersign verify <receipt.json | 0xdigest> [--ledger url] recovers the EIP-712 signature locally. A bare digest is then checked against the Tersign ledger unless --ledger names another; a receipt file verifies offline and touches no chain at all. The ledger consulted is always printed. Prefer raw HTTP? The same proof, no CLI:
curl https://tersign.ai/v1/receipts/0xe5874f1ffe87f0a6dd9eb157730f67b86ee4538b125fe30fcc4e165213dd3fc4/verifyRelated MCP server: touchstone-mcp
One-Call Disclosure Evidence
Counter-signed evidence that your agent presented a disclosure — one command, no account:
npx tersign disclose "You are chatting with an AI assistant." --medium chat --agent-id my-agentThe text is digested locally (only the digest travels — data-minimization by construction). Your key signs the record; the ledger counter-signs it into a per-signer hash chain whose head is submitted for Bitcoin anchoring on a six-hourly cron. First call self-provisions a free signer-keyed account bound set-once to your key (key resolution: TERSIGN_SELLER_KEY env → macOS keychain tersign-signer → ~/.tersign/signer.key, created on first use). Free tier is quota- and rate-limited — limits. What this is: independently verifiable evidence the disclosure was attested at that time. What it is not: a compliance certification.
Chain of Custody
Every entry takes the same path: the seller signs the receipt (EIP-712, x402 offer-receipt extension) → Tersign computes the keccak256 canonical digest → the digest joins that seller's hash chain, each seq n bound to seq n−1 → the neutral ledger counter-signs (secp256k1) → anyone verifies, and any venue gets a serialized envelope.
Since 2026-08-28 each anchor stamps a chain commitment — an accumulator over every counter-signed link — so one anchored digest covers the whole prefix; rows anchored earlier bind the head record only and say so (subjectSchema).
graph LR
A["agent transaction<br/>x402"] --> B["seller-signed receipt<br/>EIP-712"]
B --> C["canonical digest<br/>keccak256"]
C --> D["per-seller hash chain<br/>seq n binds seq n−1"]
D --> E["neutral counter-signature<br/>secp256k1 ledger"]
E --> F["verifiable by anyone<br/>venue-ready envelope"]Diagram renders on GitHub. On npm, the paragraph above IS the diagram.
Refunds chain back to the original receipt via refundOf. Disputes attach to the digest with objective reason codes. Party statements are structurally segregated behind an UNVERIFIED marker — the evidence stays prompt-injection-hardened.
Enter the Record
npm i tersignwithAssure() wraps your x402 fetch handler so every paid call issues a signed, chained receipt. The full register:
Capability | In the record |
Receipts | Seller-signed EIP-712 (x402 offer-receipt extension), keccak256 canonical digests |
| x402 fetch-handler adapter — a receipt per paid call |
Compliance exports | EU Art-226b minimal tier · EN 16931 full tier · HK IRO s.51C retention |
Action records |
|
Refunds | Chained to the original receipt via |
Disputes v0 | Objective reason codes, evidence submission, adjudication |
Venue envelopes | Internet Court (5,000-char slot) · Kleros ERC-1497 · UMA · generic |
Evidence packs |
|
Idempotency | In-memory + Cloudflare D1 stores |
| Audit capture at the MCP boundary — a signed, digest-only action record per tool call (experimental) |
Capture at the MCP Boundary — tersign intercept
An agent's tool calls are usually recorded, if at all, by the party running the agent. Put a recording clamp on the wire instead:
npx tersign intercept -- npx your-mcp-serverThe proxy is a pure observer: bytes reach the server and the client exactly as sent, in
order, unmodified. Every tools/call it sees becomes an ActionRecordV1 signed by your key
and counter-signed into a hash chain — digests only, so the record proves what happened
without carrying arguments or results anywhere. Records go to a configured ledger, and fall
back to a local ~/.tersign/intercepts-<date>.jsonl so evidence is never silently dropped.
Experimental, and deliberately unopinionated about where the protocol lands: it implements the observation semantics of the audit-mode validator described in MCP SEP-2624 (Draft) as a transport-level proxy today, and is structured to move onto the interceptor primitive if and when that stabilizes. It makes no conformance claim to that draft.
For Agents — the MCP Server
npx tersign starts the MCP server (stdio). Official registry entry: io.github.tersignhq/evidence (active).
{
"mcpServers": {
"tersign": {
"command": "npx",
"args": ["tersign"],
"env": { "TERSIGN_SELLER_KEY": "0x<your-seller-key>" }
}
}
}Tools — issue_receipt · verify_receipt · verify_compliance_record · record_disclosure · record_refund · open_dispute · submit_dispute_evidence · adjudicate_dispute · get_dispute
Env var | Required | Purpose |
| yes | 0x-prefixed private key that signs your receipts and records |
| no | hosted ledger for counter-signing + chain checks |
| no | your seller API key on that ledger |
| no | your seller id on that ledger |
| no | issuer name stamped on action records |
| no | issuer jurisdiction stamped on action records |
Cold to counter-signed in one session: call issue_receipt, then check the issued receipt's digest with npx tersign verify <digest> --ledger <url>.
The agent skill tersign-evidence ships at tersignhq/skills.
The Live Record
Ledger + dashboard — public verify page: https://tersign.ai/verify
Census — hash-chained observations across the live x402 seller catalog, probed autonomously; the numbers are served live, never quoted stale: https://prober.tersign.ai/v1/prober/stats
Conformance — RFC 8785 (JCS) canonical serialization, keccak256 digests, and the public two-sided vector suite (canonical bytes, number domain, content address, chain continuity, completeness, anchored existence, phase separation, offer binding, independence — every criterion carrying both an accepting and an adversarial vector): tersignhq/evidence-record-conformance. Reproduce the bytes and your implementation is conformant — in any language.
Standards — the
compliance-fieldsextension — a typed compliance-record schema plus four evaluator-side disqualifications (independence, completeness/existence, economic-phase separation, and commitment scope — an independence claim reaches exactly as far as the record's own commitments), each executable as a two-sided conformance vector — is under review upstream (x402-foundation/x402#2853) and referenced in the x402 TSC's evidence-record charter agenda (tsc#4). The merged offer-receipt spec already carries post-session verification guidance — signer authorization evaluated as ofissuedAt, with mutable-source rotation handled explicitly (#2811, merged); the completeness, independence, existence and phase disqualifications are the open extension's normative core.
Machine Surfaces
Full URLs, readable without auth. If you are an agent, start here.
Surface | Address |
npm package |
|
MCP registry |
|
ARD catalog (Agentic Resource Discovery) | |
Verify API |
|
Envelope API |
|
Ledger stats |
|
Ledger signer |
|
Bundle verifier, out-of-band | https://tersign.ai/verify/v1/ — |
llms.txt | https://raw.githubusercontent.com/tersignhq/tersign-js/main/llms.txt |
Conformance vectors (RFC 8785 + keccak256) | https://github.com/tersignhq/tersign-js/blob/main/test/fixtures/canonical-vectors.json |
Sample action record + digests | https://github.com/tersignhq/tersign-js/blob/main/test/fixtures/compliance-record.json |
Genesis verify |
|
Contributing — read this before opening a pull request
tersignhq/tersign-js is a publish snapshot, not the development repository. Each release
overwrites src/, test/ and the packaged manifests wholesale from an upstream working tree, so
a pull request opened here cannot be merged in any durable way — the next release would silently
erase it. That is a property of the pipeline, not a judgement on the change.
Contributions are wanted; the mechanics just have to route around that:
Bugs, questions, spec disagreements — open an issue here. Issues are read, and they are the right surface for anything that does not need to touch this tree.
Code changes — open the issue first with the diff or a description. The change is applied upstream preserving your authorship, released, and the issue closed with a link to the version that carries your work. Credit follows commit authorship, not a merge badge.
Conformance disagreements — the two-sided vector suite at tersignhq/evidence-record-conformance takes pull requests normally, and is the better venue for "this criterion is wrong" or "here is the case it misses." External vectors have been merged there.
If a maintainer ever asks you to reopen work elsewhere because of this, that is why.
Available Tools
9 toolsadjudicate_disputeAdjudicate disputeA
Trigger deterministic adjudication of an open dispute. The v0 rulebook is public and the verdict is recomputable by anyone from the chain — no discretion, no model in the loop. Side effects: writes a verdict entry, and a refund verdict automatically creates the corresponding refund record. Adjudicating twice is not meaningful; the first verdict stands. Returns the verdict, the rationale naming the rule applied, and the ledger signature over both.
| Name | Required | Description | Default |
|---|---|---|---|
| disputeDigest | Yes | 0x-prefixed digest of the open dispute to adjudicate, as returned by open_dispute |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral disclosure burden. It explicitly lists side effects—writes a verdict, may create a refund record—and additional traits like deterministic outcome, public recomputability, first-verdict-wins semantics, and the ledger signature in the return value.
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?
Three dense sentences front-load the core action, then cover side effects and return values. Every sentence adds necessary information with no redundant or filler wording.
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 one parameter, no output schema, and no annotations, the description is remarkably complete: it covers preconditions, side effects, idempotency, determinism, and return shape. An agent has enough context to invoke the tool correctly and anticipate consequences.
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 100% with a single well-documented parameter including format and provenance ('as returned by open_dispute'). The tool description doesn't add further parameter-level semantics, so the baseline of 3 applies.
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 verb and resource: 'Trigger deterministic adjudication of an open dispute.' It also distinguishes the tool through deterministic rulebook language and 'no discretion, no model in the loop,' clearly separating it from related dispute workflow tools like open_dispute and get_dispute.
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 gives clear context: it applies to an 'open dispute' and warns that 'adjudicating twice is not meaningful; the first verdict stands.' It does not explicitly name alternatives or when-not-to-use relative to sibling tools, but the precondition and idempotency warning provide solid usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_disputeGet dispute recordA
Fetch a dispute in full: its state, both sides' evidence references, the verdict and rationale once adjudicated, and the ledger signature over the record. Read-only — one network read, no key required, and safe to poll while a dispute is open.
| Name | Required | Description | Default |
|---|---|---|---|
| disputeDigest | Yes | 0x-prefixed digest of the dispute to fetch, as returned by open_dispute |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral disclosure burden and does so well. It explicitly states 'Read-only — one network read, no key required, and safe to poll while a dispute is open', giving agents clear expectations about side effects, authentication, cost, and polling safety.
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 zero filler. The first sentence front-loads the purpose and return contents; the second delivers the behavioral caveats. Every sentence earns its place.
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 simple single-parameter fetch tool with no output schema, the description is complete: it explains what the response contains, that the call is read-only and cheap, and that polling is safe. No critical operational detail is missing.
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 100%, so the parameter disputeDigest is already fully documented in the schema, including format and provenance ('as returned by open_dispute'). The tool description adds no additional parameter-level meaning, so the baseline of 3 is appropriate.
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 verb ('Fetch') and resource ('a dispute in full'), and enumerates what is returned: state, both sides' evidence references, verdict and rationale, and ledger signature. It clearly distinguishes itself from the dispute-mutation siblings by emphasizing read-only access.
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 gives clear context for when the tool is appropriate: it is a read-only fetch, requires no key, and is safe to poll while a dispute is open. It does not explicitly say 'use this instead of X', but the read-only framing makes the correct use case obvious relative to sibling tools like open_dispute and adjudicate_dispute.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
issue_receiptIssue signed receiptA
Issue an x402 offer-receipt (EIP-712) plus a Tersign action record for a payment that has ALREADY settled, and counter-sign both into your hash chain when a ledger is configured. Use this for money that moved; use record_disclosure for a non-payment agent action. Side effects: signs with TERSIGN_SELLER_KEY, and performs ONE network write to the ledger when TERSIGN_LEDGER_URL/_API_KEY/_SELLER_ID are set (without them it signs locally and returns an unchained artifact). Returns the signed receipt artifact, its keccak256 canonical digest, and — when chained — the ledger counter-signature and sequence number.
| Name | Required | Description | Default |
|---|---|---|---|
| payer | Yes | 0x address that paid — the party who can later open a dispute against this receipt | |
| txHash | No | on-chain settlement transaction hash, when one exists; omit for off-chain or fiat settlement | |
| network | Yes | settlement network as CAIP-2, e.g. "eip155:8453" for Base mainnet | |
| currency | No | settlement currency code, e.g. "USDC" or "USD" | |
| principal | No | the party on whose authority the paying agent acted (x402 sense: the buyer who delegated). Omit when a human paid directly | |
| settledAt | No | unix seconds when settlement occurred; defaults to now. Set it explicitly when back-filling | |
| taxScheme | No | tax regime the seller is accounting under; recorded, never computed — Tersign does not calculate tax | |
| resourceUrl | Yes | absolute URL of the resource that was paid for; appears verbatim in the receipt | |
| supplyDescription | Yes | what was supplied, in the seller's own words; the human-readable line an auditor or venue reads |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries full responsibility. It clearly discloses signing side effects (TERSIGN_SELLER_KEY), conditional network writes, local-signing fallback, and the returned artifact's unchained state. It does not disclose whether the 'ONE network write' is idempotent or reversible, but it covers the major side effects well for a signing/ledger 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 dense but well-structured: purpose, usage rule, side effects, and return value are presented in a logical order. Every sentence contributes value, though the first sentence is long and packs several distinct facts. It is appropriately sized for a complex tool with nine parameters and no annotations.
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 nine-parameter tool with no output schema and no annotations, the description covers the core distinction, side effects, and return values. It lacks explicit return value structure or error cases, but the description does list the returned digest and ledger signature. Minor gaps remain around error behavior and exact configuration requirements, but it is stronger than typical tool descriptions.
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 100%, so every parameter already has a schema description. The tool description adds marginal semantics by explaining why settledAt should be set explicitly for back-filling and by clarifying that taxScheme is recorded but never computed. These are useful but not extensive, so a baseline 3 is appropriate.
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 opens with a specific verb ('Issue') and a precise resource ('an x402 offer-receipt (EIP-712) plus a Tersign action record'), then immediately scopes it to already-settled payments. It distinguishes itself from record_disclosure by naming it and stating the alternative use case, so an agent can disambiguate without opening the schema.
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 explicitly states when to use this tool ('Use this for money that moved') and explicitly names the alternative ('use record_disclosure for a non-payment agent action'). It also describes configuration-dependent behavior for ledger wiring, which tells the agent under what conditions chaining occurs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_disputeOpen disputeA
Open an objective dispute against a counter-signed receipt as the PAYER (the configured key must be the receipt payer). Reasons: not_delivered, wrong_content, duplicate_charge. Contested non-mechanical claims escalate to the arbiter; duplicate_charge is decided instantly from ledger arithmetic.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | Yes | grounds: 'not_delivered' nothing arrived · 'wrong_content' delivered but not what was bought · 'duplicate_charge' the same supply was billed twice (decided mechanically from the chain, no arbiter) | |
| statement | No | for humans reading the record — never an adjudication input | |
| claimAmount | Yes | amount claimed back, as a decimal STRING in the receipt's settlement currency, e.g. "12.50"; must not exceed the receipt amount | |
| receiptDigest | Yes | 0x-prefixed keccak256 digest of the counter-signed receipt being disputed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral disclosure burden. It usefully discloses the payer-key prerequisite, the three grounds, and the different adjudication paths (arbiter vs. instant ledger arithmetic). It does not mention post-submission effects or reversibility, but the core behavioral traits are well covered.
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?
Three sentences with no filler. The purpose and role are front-loaded, followed by reasons and behavioral outcome. Every sentence contributes information an agent needs before invoking the tool.
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 adequately covers who can call the tool (payer), the permitted reasons, and what happens after submission (arbiter or instant decision). With no output schema and no annotations, it would benefit from a note on side effects or dispute lifecycle, but the core calling context is present and sufficient for correct invocation.
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 100%, so the baseline is 3. The description repeats the reason enum values but adds no new parameter-specific meaning; the schema already documents receiptDigest, claimAmount, statement, and each reason in detail.
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?
States a specific verb ('Open'), a specific resource ('dispute against a counter-signed receipt'), and the required role ('as the PAYER'). The enumeration of reasons and escalation behavior clearly distinguishes it from sibling tools like submit_dispute_evidence and adjudicate_dispute.
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?
Provides clear context: only the receipt payer can open, and the three allowed reasons are enumerated. It also clarifies that non-mechanical claims escalate to the arbiter while duplicate_charge is instant, which helps an agent decide when this tool is appropriate. It does not explicitly state when to use alternatives like submit_dispute_evidence or adjudicate_dispute, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
record_disclosureRecord counter-signed disclosureA
One-call disclosure evidence (EU AI Act Art 50 dialect): digests the disclosure text LOCALLY, signs an action record with your key, and the public ledger counter-signs it into your per-signer hash chain. No API key needed — first call self-provisions a free signer-keyed account.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | what was disclosed: 'ai-interaction' = the user was told they are talking to an AI; 'synthetic-content' = output was marked machine-generated. Defaults to 'ai-interaction' | |
| text | No | the disclosure text as presented — digested locally, never transmitted | |
| medium | No | channel: 'chat' | 'api' | 'voice' | 'ui' … | |
| agentId | Yes | stable identifier for the disclosing agent — keep it constant across calls so one chain accumulates per agent | |
| textDigest | No | pre-computed digest (wins over text) | |
| resourceUrl | No | absolute URL of the surface the disclosure was presented on, when there is one |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses local digesting, signing with the caller's key, public-ledger counter-signing, per-signer hash chains, and free self-provisioning. It does not explicitly state irreversibility or post-record behavior, but the public-ledger and hash-chain wording makes the durable write intent clear.
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?
Two sentences with no filler: the first states purpose and mechanism, the second adds the key onboarding fact. Important details such as local processing and no API key are front-loaded.
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 six parameters, no output schema, and no annotations, the description plus schema cover the workflow, onboarding, and key parameter semantics. The main gap is an explicit return/result description, though the schema's chainId note partially covers what the first call produces.
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 already documents most parameters, so the baseline is 3; the description adds useful cross-cutting meaning by mapping 'digests the disclosure text LOCALLY' to text/textDigest, 'signs an action record with your key' to signingKey, and 'per-signer hash chain' to agentId/chainId. It does not enumerate every parameter, but the schema fills those details.
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 names a concrete action and resource: recording one-call disclosure evidence under the EU AI Act Art 50, with a clear mechanism (local digest, signing, public-ledger counter-signing). This is distinct from sibling tools like record_refund and verify_compliance_record, so an agent can identify the tool's purpose without ambiguity.
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 provides a clear when-to-use context: when EU AI Act Art 50 disclosure evidence is needed, and it stresses a one-call, no-API-key flow. It does not explicitly enumerate when not to use it or name sibling alternatives, but the regulatory use case is specific enough to route the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
record_refundRecord refundA
Record a refund against an already-chained receipt, as the SELLER. The refund becomes its own counter-signed entry that references the original — nothing is edited or deleted, so the chain stays append-only and both the charge and the refund remain visible. Requires ledger configuration (TERSIGN_LEDGER_URL/_API_KEY/_SELLER_ID) and performs one network write; errors if the original digest is not on your chain. This RECORDS a refund you have already made — it moves no money. Returns the refund record, its digest, the ledger counter-signature and sequence number.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | refunded amount as a decimal STRING in the original settlement currency, e.g. "12.50". A string, not a number, so no precision is lost. Partial refunds are allowed | |
| reason | Yes | why the refund was issued, in your own words; recorded verbatim for whoever reads the chain later | |
| originalDigest | Yes | 0x-prefixed keccak256 digest of the receipt being refunded — the digest returned by issue_receipt, and it must already exist on your chain |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it delivers: it discloses append-only immutability ('nothing is edited or deleted'), the network write side effect, environment prerequisites, the error condition for a missing original digest, and the semantic limitation that it moves no money. This is exemplary behavioral disclosure.
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?
Four sentences, each carrying distinct value: role/purpose, chain semantics, requirements/error behavior, and semantic boundary/return values. There is no filler, though the description is slightly longer than strictly necessary; it remains well-structured and front-loaded.
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 no output schema and no annotations, the description is unusually complete: it states prerequisites (ledger config), side effect (one network write), error condition (digest not on chain), role constraint, and return values (record, digest, counter-signature, sequence number). An agent has what it needs to invoke the tool correctly without digging elsewhere.
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 input schema already documents all three parameters with 100% coverage, including amount as a precision-preserving decimal string, reason as verbatim text, and originalDigest with regex pattern and existence requirement. The description adds essentially no new parameter-level meaning beyond what the schema states (e.g., original digest must exist), so a baseline 3 is appropriate.
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 opens with 'Record a refund against an already-chained receipt, as the SELLER', stating a specific action, target resource, and role. It clearly distinguishes this from issue_receipt and other tools by focusing on refunds of already-chained receipts and explicitly noting it records an already-made refund rather than creating the original charge.
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 gives clear context: use this when you are the seller and have already made a refund, and you need to record it against an existing receipt. It also clarifies a boundary ('moves no money') and a prerequisite (ledger configuration). It does not explicitly name alternative tools or list when-not-to-use conditions, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_dispute_evidenceSubmit dispute evidenceA
Submit signed evidence to an open dispute. Claimant evidence must be signed by the payer key; respondent evidence additionally requires the seller API key (TERSIGN_LEDGER_API_KEY).
| Name | Required | Description | Default |
|---|---|---|---|
| role | Yes | which side you are filing as: 'claimant' = the payer who opened it (payer key) · 'respondent' = the seller answering it (also needs TERSIGN_LEDGER_API_KEY) | |
| artifacts | Yes | at least one evidence reference; submit every artifact you want considered in a single call | |
| disputeDigest | Yes | 0x-prefixed digest of the open dispute, as returned by open_dispute |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral disclosure burden. It usefully reveals signing requirements and the respondent's additional TERSIGN_LEDGER_API_KEY need, but it does not mention side effects, whether submissions can be amended, idempotency, or what happens once evidence is accepted.
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?
Two tight sentences with no fluff. The core action is front-loaded, and the additional key-requirement detail is compact but essential.
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 input schema is rich and covers parameters thoroughly, but there is no output schema and no description of the response, submission lifecycle, or whether multiple submissions are allowed. For a write-style tool with no annotations, an agent still lacks closure on what happens after the call.
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 100%, so the schema already documents parameters, but the description still adds value beyond it. It ties the 'role' enum to concrete key requirements and clarifies what 'signed evidence' means operationally, which directly informs correct parameter selection.
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 starts with a specific verb and object — 'Submit signed evidence' — and qualifies it with 'to an open dispute,' making the tool's role unmistakable. This clearly distinguishes it from sibling tools like open_dispute, get_dispute, and adjudicate_dispute.
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 phrase 'open dispute' provides clear context for when this tool is appropriate, and the role distinction explains the two filing sides. However, it does not explicitly name alternatives or state when not to use it, such as before a dispute is opened or after adjudication.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_compliance_recordVerify compliance recordA
Verify a Tersign action record against its attestation: recompute the record's canonical digest, confirm the attestation commits to that exact digest, and recover the signature. Fully OFFLINE — no network, no API key, no account. Use this for an action record (a disclosure or other non-payment agent action); use verify_receipt for a payment receipt. PASS proves integrity and internal consistency only. Authorship needs an out-of-band signer address: pass expectedSigner, or the identity is whatever the artifact claims about itself. Returns { valid, signer, digest }; on mismatch, valid:false plus the recovered signer and the recomputed digest.
| Name | Required | Description | Default |
|---|---|---|---|
| record | Yes | the action record object as issued (ComplianceRecordV1 shape). Pass the object, not a JSON string; any field edit changes the digest and fails verification — which is the point | |
| attestation | Yes | the attestation that accompanies the record: the signature over the record digest, as returned alongside it at issuance | |
| expectedSigner | No | 0x address the record MUST be signed by, obtained out-of-band (for the public ledger: https://tersign.ai/v1/ledger). Omit to recover the signer without enforcing it |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations available, the description carries the full burden and does so thoroughly. It discloses that the operation is fully offline with no network/API key/account, that PASS proves only integrity and internal consistency, and that authorship requires an out-of-band signer. It also specifies the return shape and mismatch behavior.
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?
Every sentence earns its place. The description front-loads the core purpose, then adds offline behavior, sibling routing, an important limitation, and the return format. It is dense but not bloated, with no redundant phrases.
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?
Despite having nested object parameters, no output schema, and no annotations, the description fully equips an agent to call the tool correctly. It covers parameter handling, return values, failure behavior, offline constraints, and the distinction from the similarly named sibling tool verify_receipt.
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?
Although schema coverage is already 100%, the description adds meaningful parameter semantics: record must be passed as an object not a string, any field edit changes the digest, attestation is the signature returned at issuance, and expectedSigner is optional but enforces authorship. This goes well beyond the schema property descriptions.
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 opens with a specific verb and resource: 'Verify a Tersign action record against its attestation', and details the mechanism (recompute canonical digest, confirm attestation commits, recover signature). It also distinguishes itself from verify_receipt, making its scope unmistakable.
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?
Explicit guidance is provided: 'Use this for an action record... use verify_receipt for a payment receipt.' It also tells the caller when to pass expectedSigner versus omit it, and warns that PASS only proves integrity, not authorship without an out-of-band signer address.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_receiptVerify signed receiptA
Verify an offer-receipt artifact: recover the EIP-712 signature and confirm the payload digest binds to it. Fully OFFLINE — no network, no API key, no account; verifying someone else's receipt is the intended use. Use this for a receipt (money); use verify_compliance_record for an action record (a non-payment action). Returns { valid, signer, digest } and, when expectedSigner is supplied and does not match, valid:false with the recovered signer so you can see who actually signed.
| Name | Required | Description | Default |
|---|---|---|---|
| artifact | Yes | the receipt artifact exactly as issued: { format, payload, signature }. Pass the object, not a JSON string | |
| expectedSigner | No | 0x address the receipt MUST be signed by — obtain it out-of-band, never from the artifact. Omit to recover the signer without enforcing it |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and does so thoroughly: it discloses fully OFFLINE operation, no network/API key/account requirement, the return shape { valid, signer, digest }, and the specific behavior when expectedSigner mismatches. This exceeds what an agent could infer from the schema alone.
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?
Three tightly packed sentences: the first states the core operation, the second adds offline constraints and the intended user, and the third covers routing and return behavior. No filler or repetition of schema content, and the most critical details are front-loaded.
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 no output schema and no annotations, the description provides all essential context: purpose, offline behavior, sibling differentiation, expectedSigner guidance, and return values. The nested artifact parameter is sufficiently described in the schema, and description-schema combined coverage leaves no critical gap for correct invocation.
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 coverage is 100%, so the baseline is 3, but the description adds meaningful semantic detail beyond the schema. It clarifies the expectedSigner behavior in the mismatch case and reinforces the artifact as an object, not a string, which helps avoid common invocation errors.
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?
States a specific verb and resource: 'Verify an offer-receipt artifact' with a clear mechanism ('recover the EIP-712 signature and confirm the payload digest binds to it'). It also distinguishes itself from the sibling verify_compliance_record by domain, leaving no ambiguity about which tool handles receipts.
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?
Explicitly says when to use this tool versus the alternative: 'Use this for a receipt (money); use verify_compliance_record for an action record (a non-payment action).' It also emphasizes the offline, no-account nature and that verifying someone else's receipt is the intended use, which guides selection.
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.
9 tool updates
v0.4.7- Changed
adjudicate_dispute1 field changed- added
Input schema / properties / disputeDigest / descriptionAdded value: +"0x-prefixed digest of the open dispute to adjudicate, as returned by open_dispute"
- Changed
get_dispute1 field changed- added
Input schema / properties / disputeDigest / descriptionAdded value: +"0x-prefixed digest of the dispute to fetch, as returned by open_dispute"
- Changed
issue_receipt9 fields changed- added
Input schema / properties / currency / descriptionAdded value: +"settlement currency code, e.g. \"USDC\" or \"USD\"" - changed
Input schema / properties / network / descriptionPrevious value: -"CAIP-2, e.g. eip155:8453"New value: +"settlement network as CAIP-2, e.g. \"eip155:8453\" for Base mainnet" - added
Input schema / properties / payer / descriptionAdded value: +"0x address that paid — the party who can later open a dispute against this receipt" - changed
Input schema / properties / principal / descriptionPrevious value: -"signed principal behind the paying agent"New value: +"the party on whose authority the paying agent acted (x402 sense: the buyer who delegated). Omit when a human paid directly" - added
Input schema / properties / resourceUrl / descriptionAdded value: +"absolute URL of the resource that was paid for; appears verbatim in the receipt" - added
Input schema / properties / settledAt / descriptionAdded value: +"unix seconds when settlement occurred; defaults to now. Set it explicitly when back-filling" - added
Input schema / properties / supplyDescription / descriptionAdded value: +"what was supplied, in the seller's own words; the human-readable line an auditor or venue reads" - added
Input schema / properties / taxScheme / descriptionAdded value: +"tax regime the seller is accounting under; recorded, never computed — Tersign does not calculate tax" - added
Input schema / properties / txHash / descriptionAdded value: +"on-chain settlement transaction hash, when one exists; omit for off-chain or fiat settlement"
- Changed
open_dispute3 fields changed- changed
Input schema / properties / claimAmount / descriptionPrevious value: -"claimed refund in the settlement currency"New value: +"amount claimed back, as a decimal STRING in the receipt's settlement currency, e.g. \"12.50\"; must not exceed the receipt amount" - added
Input schema / properties / reason / descriptionAdded value: +"grounds: 'not_delivered' nothing arrived · 'wrong_content' delivered but not what was bought · 'duplicate_charge' the same supply was billed twice (decided mechanically from the chain, no arbiter)" - added
Input schema / properties / receiptDigest / descriptionAdded value: +"0x-prefixed keccak256 digest of the counter-signed receipt being disputed"
- Changed
record_disclosure3 fields changed- changed
Input schema / properties / agentId / descriptionPrevious value: -"stable identifier for the disclosing agent"New value: +"stable identifier for the disclosing agent — keep it constant across calls so one chain accumulates per agent" - added
Input schema / properties / kind / descriptionAdded value: +"what was disclosed: 'ai-interaction' = the user was told they are talking to an AI; 'synthetic-content' = output was marked machine-generated. Defaults to 'ai-interaction'" - added
Input schema / properties / resourceUrl / descriptionAdded value: +"absolute URL of the surface the disclosure was presented on, when there is one"
- Changed
record_refund3 fields changed- added
Input schema / properties / amount / descriptionAdded value: +"refunded amount as a decimal STRING in the original settlement currency, e.g. \"12.50\". A string, not a number, so no precision is lost. Partial refunds are allowed" - added
Input schema / properties / originalDigest / descriptionAdded value: +"0x-prefixed keccak256 digest of the receipt being refunded — the digest returned by issue_receipt, and it must already exist on your chain" - added
Input schema / properties / reason / descriptionAdded value: +"why the refund was issued, in your own words; recorded verbatim for whoever reads the chain later"
- Changed
submit_dispute_evidence10 fields changed- added
Input schema / properties / artifacts / descriptionAdded value: +"at least one evidence reference; submit every artifact you want considered in a single call" - added
Input schema / properties / artifacts / items / properties / at / descriptionAdded value: +"unix seconds the artifact was produced; supply it when timing is part of your argument" - removed
Input schema / properties / artifacts / items / properties / digest / $refRemoved value: -"#/properties/disputeDigest" - added
Input schema / properties / artifacts / items / properties / digest / descriptionAdded value: +"0x-prefixed keccak256 digest of the artifact. Only the DIGEST is submitted — the content itself never leaves your side" - added
Input schema / properties / artifacts / items / properties / digest / patternAdded value: +"^0x[0-9a-fA-F]{64}$" - added
Input schema / properties / artifacts / items / properties / digest / typeAdded value: +"string" - added
Input schema / properties / artifacts / items / properties / kind / descriptionAdded value: +"what this artifact is; the adjudicator treats each kind differently" - added
Input schema / properties / artifacts / items / properties / note / descriptionAdded value: +"short human-readable label for whoever reads the record; never an adjudication input" - added
Input schema / properties / disputeDigest / descriptionAdded value: +"0x-prefixed digest of the open dispute, as returned by open_dispute" - added
Input schema / properties / role / descriptionAdded value: +"which side you are filing as: 'claimant' = the payer who opened it (payer key) · 'respondent' = the seller answering it (also needs TERSIGN_LEDGER_API_KEY)"
- Changed
verify_compliance_record3 fields changed- added
Input schema / properties / attestation / descriptionAdded value: +"the attestation that accompanies the record: the signature over the record digest, as returned alongside it at issuance" - added
Input schema / properties / expectedSigner / descriptionAdded value: +"0x address the record MUST be signed by, obtained out-of-band (for the public ledger: https://tersign.ai/v1/ledger). Omit to recover the signer without enforcing it" - added
Input schema / properties / record / descriptionAdded value: +"the action record object as issued (ComplianceRecordV1 shape). Pass the object, not a JSON string; any field edit changes the digest and fails verification — which is the point"
- Changed
verify_receipt2 fields changed- changed
Input schema / properties / artifact / descriptionPrevious value: -"the receipt artifact object {format, payload, signature}"New value: +"the receipt artifact exactly as issued: { format, payload, signature }. Pass the object, not a JSON string" - added
Input schema / properties / expectedSigner / descriptionAdded value: +"0x address the receipt MUST be signed by — obtain it out-of-band, never from the artifact. Omit to recover the signer without enforcing it"
9 tool updates
v0.2.0- First observed
adjudicate_dispute - First observed
get_dispute - First observed
issue_receipt - First observed
open_dispute - First observed
record_disclosure - First observed
record_refund - First observed
submit_dispute_evidence - First observed
verify_compliance_record - First observed
verify_receipt
TDQS
Scored across 9 tools
Each tool has a clear operational boundary: payment receipt issuance and refunds are distinct from disclosure recording, and verification tools are split by artifact type. The dispute tools form a separate, well-defined lifecycle, and the descriptions actively cross-reference the correct counterpart tool.
All tool names follow a consistent verb_noun snake_case convention. Verification, recording, and dispute actions use predictable verbs, and the multiword nouns are consistently descriptive.
Nine tools is well-scoped for the stated domain. Each tool corresponds to a necessary step in the receipt, compliance, refund, or dispute workflow with no redundant helpers or superficial wrappers.
The surface covers the full intended lifecycle: issue and verify payment receipts, record and verify disclosures, handle refunds, and open, evidence, adjudicate, and fetch disputes. The append-only design makes updates/deleties unnecessary, and the returned artifacts avoid dead ends.
Maintenance
Related MCP Connectors
MCP server for Boson Protocol — on-chain agentic commerce for physical & digital goods.
Tenzro Network MCP server: wallet, identity, payments, inference, staking, bridges, verification.
Public read-only MCP server for HODLXXI agent identity, trust, receipts, and verification.
Tamper-evident proof creation and verification for AI agents via MCP, A2A, and REST.
Related MCP Servers
- FlicenseDqualityCmaintenanceMCP server for the Recite API, enabling receipt scanning, transaction management, batch processing, and local ledger workflows for agents.57-

touchstone-mcpofficial
AlicenseNot gradedqualityBmaintenanceLocal MCP server that signs and records agent actions into a tamper-evident log using Ed25519 keys for frictionless integration with Touchstone.29Apache 2.0- AlicenseNot gradedqualityCmaintenanceAn MCP server providing an append-only, hash-chained evidence ledger for agent actions, where every record is a tamper-evident receipt cryptographically bound to all prior records and persisted as human-readable JSONL local state. It exposes tools to append records, verify chain integrity (pinpointing tampering), query records by actor/action/target/time, and fetch ledger stats—with no update or delete capabilities by design.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceAn MCP server that provides append-only, tamper-evident local receipts for AI agent actions, capturing command executions, outputs, and handoff evidence.MIT