Skip to main content
Glama

ASPERN: counterparty checks for agents

Test purchase, without paying

test_purchase

WALK THE WHOLE PURCHASE OF AN x402 ENDPOINT WITHOUT PAYING, in the order a buyer actually asks the questions, stopping at the first one that objects. All five are asked in one pass and in that order, so the walk stops where a buyer would stop. Five steps: is the endpoint there, what does it charge RIGHT NOW, does the seller’s own catalogue entry agree with what it just said, does the record say anything against paying that payee under a published policy, and — the step that only exists because this is a rehearsal — is the price still the one the decision was made on, re-read a moment later. A quote that moved between the decision and the signature would authorise something nobody decided on. THE VERDICT HAS THREE STATES AND cannot-tell IS NOT would-proceed: an unanswered question is never rounded up to a passed one. quotedRaw is what the endpoint said, in the asset’s smallest unit, and quotedUsd is NULL unless the catalogue carries both halves of the same token’s pair to scale it — nothing in a payment-requirements document names the decimals, and a figure scaled by a guessed exponent is a hundred-fold error waiting to be quoted. We knock only on endpoints already in the x402 catalogue we read, at most one live handshake a minute per resource, because we knock only on what the catalogue already lists: a URL named in a request is not by itself a reason to send traffic to somebody else’s host. Nothing is signed and nothing is spent. FREE.

Input Schema

NameRequiredDescriptionDefault
fillNoValues for the slots the SELLER’s own catalogue URL declares, e.g. `{"doi": "10.1000/xyz"}` for a resource listed as `…?doi={doi}`. A SMALL PART of the catalogue is templates rather than plain addresses — `askedWithUnfilled` on the answer names the slots for the endpoint in front of you — and without this we knock with `{doi}` where a value belongs and answer a question nobody asked. ONLY declared slots are accepted: a name the template does not contain is REFUSED rather than ignored, because a parameter silently dropped would let you read the answer as being about the call you meant to make. Values are percent-encoded and the filled URL is verified to reach the same origin and path shape as the catalogue entry, so a value can never choose the host — not even a slot the seller put in their own hostname. A filled rehearsal is ALWAYS a live knock, so inside the one-a-minute cooldown it answers 429 rather than serving back the reading of the unfilled question; and it is NOT written to the endpoint history, because two different questions in one run series would look like a price that moved.
policyNoA policy version or slug to decide under. Defaults to conservative-v1.
resourceYesThe http(s) endpoint to rehearse buying. It must be one the x402 catalogue already holds; `list_x402_endpoints` finds it.

Output Schema

NameRequiredDescriptionDefault
liveNoWhether the handshake happened just now or is the stored reading from within the last minute. A stored reading is a weaker claim and this says which it is.
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: where a careful buyer stops and why, or what could not be answered. An unanswered question is named rather than passed over.
payeeNoThe address the ENDPOINT named in its handshake, which is not always the one its listing names. That disagreement is step three.
stepsNoOne per question, in the order a buyer asks them. Each carries `asks` in a person’s words, `state`, `stops` and `says`.
becauseNoThe NAME of the finding that decided it, two or three words, e.g. `Payee mismatch` or `Price moved`. NULL only where nothing decided, which is a clean walk: a verdict must not assert a cause it did not measure.
historyNoEVERY TIME WE HAVE KNOCKED, which is the half a checker cannot hold: it sees the endpoint now, only we hold the record of each time we looked. `state` is `answering`, `not-answering`, `unconfirmed` (one failure, which is a reason to ask again and not a finding), `seen-once` or `never-knocked` — the last two are about OUR reach and not about the seller. An outage is published as a RANGE and never as a duration: `downAtLeastHours` counts from the first knock that failed and `downAtMostHours` from the last that answered, because the stop happened somewhere between and that window is as wide as the gap between two knocks. `downAtMostHours` is NULL where nothing has ever answered, since there is then no moment to measure from and zero would read as a bound we do not have. `answered` of `knocks` is the denominator for everything here, `runs` is the timeline oldest first with a knock COUNT per run rather than a span, and `longestFailureRun` is counted in knocks for the same reason. NULL where the endpoint is not one we knock on.
networkNoThe chain the endpoint asked to be paid on, as it stated it, usually CAIP-2.
verdictNo`would-proceed`, `would-stop` or `cannot-tell`. The third is NOT the first.
headlineNoThe outcome in three words or fewer: `Purchase stopped`, `Cannot tell` or `A careful buyer would go ahead`. Same fact as `verdict`, in a reader’s words.
resourceYesThe endpoint this is about, read back.
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.
askedWithNoThe values we put in, read back, so you can see the question that was actually asked. NULL where you sent none, which is the ordinary case.
cannotSeeNoWhat no rehearsal establishes however well it goes.
decidedAtNoThe id of the step that stopped it, so a caller acts on a step rather than parsing a sentence.
knockedOnNoThe URL we actually knocked on once your values were in it. NULL where you sent none, in which case it is `resource` unchanged.
quotedRawNoWhat it asked for, in the asset’s smallest unit. Always the number the endpoint actually said.
quotedUsdNoThe same amount in dollars, NULL where we could not scale it from the catalogue’s own pair.
rehearsedNoFalse where the endpoint is not in the catalogue, with `says` explaining that we do not fetch a URL because a request named it.
askedWithUnfilledNoPlaceholders in the catalogue URL we sent UNFILLED, e.g. `doi`. Empty is the ordinary case: the URL is an address, not a template. Non-empty qualifies the PRICE and not the availability — the endpoint answered and quoted, but for a call with a gap in it, so the figure may be the generic one rather than the price of the call you mean to make. Templates are a small part of the catalogue and `askedWithUnfilled` names the slots on each answer.
walkedPastTheStopNoTRUE where a question after the stopping one was still asked, which is deliberate: halting at the first objection would hide a second. FALSE means the stop was the last thing asked, or nothing stopped at all. Either way nothing financial happened, because none of these steps signs or spends.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changed
    • changedInput schema / properties / fill / description
      Previous value: -"Values for the slots the SELLER’s own catalogue URL declares, e.g. `{\"doi\": \"10.1000/xyz\"}` for a resource listed as `…?doi={doi}`. 1,730 of 55,343 catalogued resources are templates, and without this we knock with `{doi}` where a value belongs and answer a question nobody asked. ONLY declared slots are accepted: a name the template does not contain is REFUSED rather than ignored, because a parameter silently dropped would let you read the answer as being about the call you meant to make. Values are percent-encoded and the filled URL is verified to reach the same origin and path shape as the catalogue entry, so a value can never choose the host — not even a slot the seller put in their own hostname. A filled rehearsal is ALWAYS a live knock, so inside the one-a-minute cooldown it answers 429 rather than serving back the reading of the unfilled question; and it is NOT written to the endpoint history, because two different questions in one run series would look like a price that moved."New value: +"Values for the slots the SELLER’s own catalogue URL declares, e.g. `{\"doi\": \"10.1000/xyz\"}` for a resource listed as `…?doi={doi}`. A SMALL PART of the catalogue is templates rather than plain addresses — `askedWithUnfilled` on the answer names the slots for the endpoint in front of you — and without this we knock with `{doi}` where a value belongs and answer a question nobody asked. ONLY declared slots are accepted: a name the template does not contain is REFUSED rather than ignored, because a parameter silently dropped would let you read the answer as being about the call you meant to make. Values are percent-encoded and the filled URL is verified to reach the same origin and path shape as the catalogue entry, so a value can never choose the host — not even a slot the seller put in their own hostname. A filled rehearsal is ALWAYS a live knock, so inside the one-a-minute cooldown it answers 429 rather than serving back the reading of the unfilled question; and it is NOT written to the endpoint history, because two different questions in one run series would look like a price that moved."
    • changedOutput schema / properties / askedWithUnfilled / description
      Previous value: -"Placeholders in the catalogue URL we sent UNFILLED, e.g. `doi`. Empty is the ordinary case: the URL is an address, not a template. Non-empty qualifies the PRICE and not the availability — the endpoint answered and quoted, but for a call with a gap in it, so the figure may be the generic one rather than the price of the call you mean to make. 1,730 of 55,343 catalogued resources are templates."New value: +"Placeholders in the catalogue URL we sent UNFILLED, e.g. `doi`. Empty is the ordinary case: the URL is an address, not a template. Non-empty qualifies the PRICE and not the availability — the endpoint answered and quoted, but for a call with a gap in it, so the figure may be the generic one rather than the price of the call you mean to make. Templates are a small part of the catalogue and `askedWithUnfilled` names the slots on each answer."
    • 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"
      +}
  2. Added

TDQS

A3.8/5.0
Behavior5/5

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

With annotations that only say readOnlyHint=false and openWorldHint=true, the description adds a great deal the agent could not otherwise know: the one-live-handshake-per-minute throttle, the 429 returned for a filled rehearsal inside the cooldown, the fact that filled rehearsals are excluded from endpoint history (implying unfilled ones are not), the three-state verdict rule that cannot-tell is never rounded up, and the guarantee that nothing is signed or spent. It also explains that quotedUsd is NULL when the catalogue lacks both halves of the token pair. This is rich disclosure well beyond the annotations.

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

Conciseness3/5

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

The purpose is front-loaded and most sentences carry distinct information, but the prose is heavily stylized ('we knock', 'a hundred-fold error waiting to be quoted') and repeats the catalogue-gating point twice. It is noticeably oversized for the payload of facts delivered, costing clarity despite the information density.

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

Completeness4/5

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

For a high-complexity, open-world tool with three parameters, a nested object, and an output schema, the description covers prerequisites, rate limits, side effects, and the semantics of the three verdict states. Return-value detail is partly explained despite the output schema existing, and nothing an agent needs to call it safely appears to be missing.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already carries the bulk of parameter meaning, including the detailed `fill` template-slot contract and the conservative-v1 default for `policy`. The description reinforces those points (only declared slots accepted, nothing silently dropped, origin/path pinned) but adds little syntax or format detail the schema does not already state, so the baseline of 3 applies.

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

Purpose4/5

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

The opening sentence names a specific verb (rehearse/walk the purchase), a specific resource (an x402 endpoint), and a specific scoping constraint (without paying), so an agent immediately knows what this does. It does not, however, name or differentiate against the many adjacent siblings (preflight_payment, check_action, evaluate_action, inspect_payment), so it falls short of a 5.

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

Usage Guidelines3/5

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

It gives prerequisites (the endpoint must already be in the x402 catalogue, discoverable via list_x402_endpoints) and discloses the one-a-minute-per-resource rate limit, which is real guidance. But it never states the decision point that selects this tool over preflight_payment or check_action, and offers no explicit when-not-to-use case.

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