Skip to main content
Glama

ASPERN: counterparty checks for agents

Weigh one payment before sending it

preflight_payment
Read-onlyIdempotent

Call this immediately before sending a payment, every time — not once per counterparty. It weighs THIS payment (the amount, the chain, the endpoint) against what the address has actually done: the price the seller themselves published for that endpoint, the address that endpoint names as its payee, the largest payment this address has ever received, and whether it has ever been paid on the chain you are about to use. Answers one of three verdicts. nothing-against-it means every check ran and none objected — it is NOT a statement that the payment is safe, because nothing here can see what the payment is for or what you agreed. look-first means at least one thing we could READ does not match, and the findings say which; a check that could not run never produces it, it produces cannot-say. cannot-say means we did not read enough to have an opinion, and must never be read as the first. Free. Give as much of amountUsd, chain and resource as you have: each one left out is a check that did not run, and the answer says so rather than passing. THE ENDPOINT’S OWN WORD OUTRANKS THE CATALOGUE: where we have probed it, branch on againstEndpoint.price.againstQuote, and below-quote is not a pass. Each named finding (live-price-differs-from-listing, quoted-payee-is-not-the-one-being-paid, below-listed-price, network-not-comparable and the rest) is explained under findings.

Input Schema

NameRequiredDescriptionDefault
toYesThe address you are about to pay.
chainNoThe chain you are about to send it on, e.g. base, polygon, solana.
resourceNoThe http(s) URL of the endpoint you are buying, where there is one. This is the sharpest check available: its catalogue entry carries the seller’s own price and their own payee address.
amountUsdNoWhat you are about to send, in US dollars.

Output Schema

NameRequiredDescriptionDefault
metaNoHow current this answer is and what it was read from: `freshness` and the ages behind it. Present on every answer from this server, whatever the tool.
saysYesThe verdict in one sentence, naming what did not match. Written to be shown to a person deciding whether to go ahead.
checkNoThe free counterparty check for this address.
limitsNoWhat this check cannot establish, in full. Quote it whenever you quote the verdict: a clean answer here is the absence of an objection, never a guarantee about the payment.
listingNoThe seller’s own catalogue entry for the resource, where there is one — their word, written once, possibly months ago.
verdictYes`nothing-against-it` means every check ran and none objected — NOT that the payment is safe. `cannot-say` means too little was read to have an opinion, and must never be read as the first. It is also the answer when nothing contradicted the payment but a check could not run, because reporting our own gap as a clean result would be the worst of the three.
evidenceNoThe common payment record, the same object as on inspect_payment: `listedPayee` from the seller’s catalogue entry, `onChainRecipient` (the address you are about to pay), `recipientIsListedPayee` (false is a finding, null means one side is missing), `facilitator`, `settlement` (`unknown`: nothing has been sent), `delivery` (`unevidenceable` on x402) and `says`.
findingsNoEvery check that ran, each with the record behind it and its own `tone` and `kind`. NOT only the ones that objected: a `tone` of `good` is a check that MATCHED, so reading this array’s length as a count of problems overstates them. Bucket on `kind` — `fact` and `signal` were established, and `unknown` means we could not see, which never counts as something standing against the payment. FINDINGS WORTH KNOWING BY NAME. `live-price-differs-from-listing` means the price has MOVED and the live figure is the one to pay. `quoted-payee-is-not-the-one-being-paid` means the endpoint asks to be paid somewhere other than where you are sending. `live-price-not-comparable` means the two prices are in different tokens or one is unnamed, so they were NOT compared rather than compared and found to agree. `below-listed-price` means the payment is under half the seller’s published price: ordinary, not an objection, and NOT a confirmation of the amount either, because the listing may price a different unit or tier; it is `neutral` and cannot improve the verdict. Paying less than the CATALOGUE’s price is a different question from `below-quote` and stays `neutral`, because a directory entry may price a different unit and was written once. `network-not-comparable` means the listing names a network we could not resolve, so the chains were not compared rather than compared and found to agree. A CAIP-2 id and a chain name are resolved through one shared map, so `eip155:8453` and `base` are the same network here and in check_action; they used to disagree.
proposalNoYour payment as we understood it: payee, amount, chain and resource. Null where too little was given to form one. Check it before reading the verdict, which is about THIS proposal and no other.
receivedNoWhat you told us, read back, so a typo is visible.
verdictsNoWhat each verdict word means, so a caller never has to guess.
warningsNoAnything the server wants a caller to know about THIS answer before acting on it. Empty is the normal case and is not a guarantee.
observationsYesEvery check that ran, including the ones that could not: a field you left out appears here as a check that did not run, rather than as silence.
againstEndpointNoWHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.againstQuote` is the one word to branch on — `exact-match`, `below-quote`, `above-quote`, `unknown` — and `below-quote` is NOT a pass: the endpoint stated what it wants for this call and less than that does not buy it unless its terms allow a partial payment, which we cannot see. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment. `below-quote` is a REVIEW and never a refusal.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedOutput schema / properties / againstEndpoint / description
      Previous value: -"WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.againstQuote` is the one word to branch on — `exact-match`, `below-quote`, `above-quote`, `unknown` — and `below-quote` is NOT a pass: the endpoint stated what it wants for this call and less than that does not buy it unless its terms allow a partial payment, which we cannot see. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment."New value: +"WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.againstQuote` is the one word to branch on — `exact-match`, `below-quote`, `above-quote`, `unknown` — and `below-quote` is NOT a pass: the endpoint stated what it wants for this call and less than that does not buy it unless its terms allow a partial payment, which we cannot see. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment. `below-quote` is a REVIEW and never a refusal."
    • changedOutput schema / properties / findings / description
      Previous value: -"Every check that ran, each with the record behind it and its own `tone` and `kind`. NOT only the ones that objected: a `tone` of `good` is a check that MATCHED, so reading this array’s length as a count of problems overstates them. Bucket on `kind` — `fact` and `signal` were established, and `unknown` means we could not see, which never counts as something standing against the payment."New value: +"Every check that ran, each with the record behind it and its own `tone` and `kind`. NOT only the ones that objected: a `tone` of `good` is a check that MATCHED, so reading this array’s length as a count of problems overstates them. Bucket on `kind` — `fact` and `signal` were established, and `unknown` means we could not see, which never counts as something standing against the payment. FINDINGS WORTH KNOWING BY NAME. `live-price-differs-from-listing` means the price has MOVED and the live figure is the one to pay. `quoted-payee-is-not-the-one-being-paid` means the endpoint asks to be paid somewhere other than where you are sending. `live-price-not-comparable` means the two prices are in different tokens or one is unnamed, so they were NOT compared rather than compared and found to agree. `below-listed-price` means the payment is under half the seller’s published price: ordinary, not an objection, and NOT a confirmation of the amount either, because the listing may price a different unit or tier; it is `neutral` and cannot improve the verdict. Paying less than the CATALOGUE’s price is a different question from `below-quote` and stays `neutral`, because a directory entry may price a different unit and was written once. `network-not-comparable` means the listing names a network we could not resolve, so the chains were not compared rather than compared and found to agree. A CAIP-2 id and a chain name are resolved through one shared map, so `eip155:8453` and `base` are the same network here and in check_action; they used to disagree."
  2. Changed1 schema field changed
    • addedOutput schema / properties / evidence
      Added value: +{
      +  "description": "The common payment record, the same object as on inspect_payment: `listedPayee` from the seller’s catalogue entry, `onChainRecipient` (the address you are about to pay), `recipientIsListedPayee` (false is a finding, null means one side is missing), `facilitator`, `settlement` (`unknown`: nothing has been sent), `delivery` (`unevidenceable` on x402) and `says`.",
      +  "type": "object"
      +}
  3. Changed2 schema fields changed
    • addedOutput schema / properties / meta
      Added value: +{
      +  "description": "How current this answer is and what it was read from: `freshness` and the ages behind it. Present on every answer from this server, whatever the tool.",
      +  "type": "object"
      +}
    • addedOutput schema / properties / warnings
      Added value: +{
      +  "description": "Anything the server wants a caller to know about THIS answer before acting on it. Empty is the normal case and is not a guarantee.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  4. Changed1 schema field changed
    • changedOutput schema / properties / againstEndpoint / description
      Previous value: -"WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment."New value: +"WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.againstQuote` is the one word to branch on — `exact-match`, `below-quote`, `above-quote`, `unknown` — and `below-quote` is NOT a pass: the endpoint stated what it wants for this call and less than that does not buy it unless its terms allow a partial payment, which we cannot see. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment."
  5. Changed2 schema fields changed
    • addedOutput schema / properties / againstEndpoint
      Added value: +{
      +  "description": "WHAT THE ENDPOINT ITSELF DEMANDED, from the 402 it answered our own unpaid request with, and how that compares. `price.evidence` ranks the three parties who can state this endpoint’s price — the endpoint’s own quote first, the catalogue second, what the address has actually been paid third — and `price.lead` names the one to act on. `price.disagreements` keeps every conflict between them with BOTH figures: a price that has moved is a finding neither source alone can show, and we never resolve it into a single number. `price.liveQuoteMatchesCatalogue` is true, false, or NULL FOR NOT COMPARABLE, which is not the same as not matching — a 402 states an amount in the asset’s smallest unit and never its decimals, so two raw figures are only the same kind of number when the token is the same; `liveQuoteMatchesCatalogueWhy` says which half is missing. `quoted` is false where we have never probed the endpoint, which is our gap and not evidence against the payment.",
      +  "type": [
      +    "object",
      +    "null"
      +  ]
      +}
    • changedOutput schema / properties / listing / description
      Previous value: -"The seller’s own catalogue entry for the resource, where there is one. The sharpest check available."New value: +"The seller’s own catalogue entry for the resource, where there is one — their word, written once, possibly months ago."
  6. Changed3 schema fields changed
    • addedOutput schema / properties / limits / description
      Added value: +"What this check cannot establish, in full. Quote it whenever you quote the verdict: a clean answer here is the absence of an objection, never a guarantee about the payment."
    • addedOutput schema / properties / proposal / description
      Added value: +"Your payment as we understood it: payee, amount, chain and resource. Null where too little was given to form one. Check it before reading the verdict, which is about THIS proposal and no other."
    • addedOutput schema / properties / says / description
      Added value: +"The verdict in one sentence, naming what did not match. Written to be shown to a person deciding whether to go ahead."
  7. Changed2 schema fields changed
    • changedOutput schema / properties / findings / description
      Previous value: -"What did not match, each with the record behind it."New value: +"Every check that ran, each with the record behind it and its own `tone` and `kind`. NOT only the ones that objected: a `tone` of `good` is a check that MATCHED, so reading this array’s length as a count of problems overstates them. Bucket on `kind` — `fact` and `signal` were established, and `unknown` means we could not see, which never counts as something standing against the payment."
    • changedOutput schema / properties / verdict / description
      Previous value: -"`nothing-against-it` means every check ran and none objected — NOT that the payment is safe. `cannot-say` means too little was read to have an opinion and must never be read as the first."New value: +"`nothing-against-it` means every check ran and none objected — NOT that the payment is safe. `cannot-say` means too little was read to have an opinion, and must never be read as the first. It is also the answer when nothing contradicted the payment but a check could not run, because reporting our own gap as a clean result would be the worst of the three."
  8. Changed9 schema fields changed
    • addedOutput schema / properties / check
      Added value: +{
      +  "description": "The free counterparty check for this address.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • removedOutput schema / properties / checksRun
      Removed value: -{
      -  "description": "Which checks actually ran. A field you left out is a check that did not.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
    • addedOutput schema / properties / limits
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / listing
      Added value: +{
      +  "description": "The seller’s own catalogue entry for the resource, where there is one. The sharpest check available.",
      +  "type": [
      +    "object",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / observations
      Added value: +{
      +  "description": "Every check that ran, including the ones that could not: a field you left out appears here as a check that did not run, rather than as silence.",
      +  "items": {
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / proposal
      Added value: +{
      +  "type": [
      +    "object",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / received
      Added value: +{
      +  "description": "What you told us, read back, so a typo is visible.",
      +  "type": "object"
      +}
    • addedOutput schema / properties / verdicts
      Added value: +{
      +  "description": "What each verdict word means, so a caller never has to guess.",
      +  "type": "object"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "verdict",
      -  "says"
      -]New value: +[
      +  "verdict",
      +  "observations",
      +  "says"
      +]
  9. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "checksRun": {
      +      "description": "Which checks actually ran. A field you left out is a check that did not.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "findings": {
      +      "description": "What did not match, each with the record behind it.",
      +      "items": {
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "says": {
      +      "type": "string"
      +    },
      +    "verdict": {
      +      "description": "`nothing-against-it` means every check ran and none objected — NOT that the payment is safe. `cannot-say` means too little was read to have an opinion and must never be read as the first.",
      +      "enum": [
      +        "nothing-against-it",
      +        "look-first",
      +        "cannot-say"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "verdict",
      +    "says"
      +  ],
      +  "type": "object"
      +}
  10. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive, and open-world behavior. The description adds substantial context beyond annotations: it defines the three verdicts, warns that `nothing-against-it` is not a safety guarantee, explains that `cannot-say` must not be read as a pass, and describes how findings and endpoint-quote precedence work.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core instruction, then explains verdicts and caveats. It is dense and occasionally verbose with all-caps emphasis, but most sentences carry actionable information for a complex preflight tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool’s complexity, annotations, and available output schema, the description is complete enough for correct invocation. It covers when to call, what each verdict means, how missing inputs affect checks, and how to interpret named findings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters. The description adds useful meaning by explaining that omitting amountUsd, chain, or resource causes specific checks not to run, and that resource is the sharpest check because it carries the seller’s published price and payee.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: weighing one payment immediately before sending it, with checks against the endpoint’s published price, payee, historical receipts, and chain activity. It also distinguishes itself from per-counterparty tools by saying 'not once per counterparty', which helps an agent tell it apart from siblings like counterparty_check.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear timing guidance ('immediately before sending a payment, every time — not once per counterparty') and explains that missing parameters cause checks not to run. It does not explicitly name alternative tools or when-not to use this one beyond the per-counterparty distinction, so it falls short of the highest bar.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources