Skip to main content
Glama

ASPERN: counterparty checks for agents

Check up to fifty addresses in one call (paid)

counterparty_bulk
Idempotent

Check up to fifty addresses in one call, each with its observations, AND what the set shares underneath: the parties that two or more of them pay. That second part is the one answer no per-address row can contain, because the input is your own shortlist — four agents stopping together because they all pay one party is invisible in four separate clean records. PAID two ways and they buy different things: one cent a call over x402, priced per call rather than per address, buys the rows; the shared block needs the dependency.shared capability, on Analyst and above, and when it is missing the block says so rather than vanishing. A shared recipient is not proof of a shared dependency — several agents paying one address may be paying a relayer, a bridge or the same customer back — and an empty list is a finding about these addresses AND about our reach. WHY readOnlyHint IS false: this tool reads and writes nothing in our store, but calling it WITH an x402 payment authorisation transfers USDC from the caller to us and records a receipt, so the call is not free of consequence and an agent must not make it speculatively. Called without an authorisation it changes nothing and answers with the price.

Input Schema

NameRequiredDescriptionDefault
addressesYesOne to fifty addresses, in any mix of forms: an EVM address in any case, a Solana base58 address, a Cardano bech32 one. Fifty-one or more is REFUSED with a 400 `too_many` rather than silently truncated, so a caller never reads a partial answer as a whole one. An address we have never seen paid comes back as a row saying so, not omitted — so the answer has one row per address you sent, in the order you sent them.

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.
itemsYesOne entry per address given, in the order given, each with its own observations and its own limits.
limitsNoWhat this answer cannot tell you.
sharedNoThe parties two or more of the given addresses pay, most shared first, each with how many of yours pay it and which ones. `available: false` with a `capability` name where the plan does not carry it. An empty list means no party is paid by more than one of them on a rail we read, which is a finding about them and about our reach: a model, an endpoint or a host shared between them is a dependency no payment rail shows.
checkedNoHow many addresses were read.
paymentNoWhat was paid and how it settled. Priced per call, not per address.
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.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changed
    • changedInput schema / properties / addresses / description
      Previous value: -"Up to 50."New value: +"One to fifty addresses, in any mix of forms: an EVM address in any case, a Solana base58 address, a Cardano bech32 one. Fifty-one or more is REFUSED with a 400 `too_many` rather than silently truncated, so a caller never reads a partial answer as a whole one. An address we have never seen paid comes back as a row saying so, not omitted — so the answer has one row per address you sent, in the order you sent them."
    • 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. Changed1 schema field changed
    • addedOutput schema / properties / shared
      Added value: +{
      +  "description": "The parties two or more of the given addresses pay, most shared first, each with how many of yours pay it and which ones. `available: false` with a `capability` name where the plan does not carry it. An empty list means no party is paid by more than one of them on a rail we read, which is a finding about them and about our reach: a model, an endpoint or a host shared between them is a dependency no payment rail shows.",
      +  "type": "object"
      +}
  3. Changed5 schema fields changed
    • addedOutput schema / properties / checked
      Added value: +{
      +  "description": "How many addresses were read.",
      +  "type": "integer"
      +}
    • addedOutput schema / properties / items
      Added value: +{
      +  "description": "One entry per address given, in the order given, each with its own observations and its own limits.",
      +  "items": {
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / limits
      Added value: +{
      +  "description": "What this answer cannot tell you.",
      +  "type": "string"
      +}
    • removedOutput schema / properties / results
      Removed value: -{
      -  "description": "One entry per address given, in the order given, each with its own observations and its own limits.",
      -  "items": {
      -    "type": "object"
      -  },
      -  "type": "array"
      -}
    • changedOutput schema / required
      Previous value: -[
      -  "results"
      -]New value: +[
      +  "items"
      +]
  4. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "payment": {
      +      "description": "What was paid and how it settled. Priced per call, not per address.",
      +      "type": "object"
      +    },
      +    "results": {
      +      "description": "One entry per address given, in the order given, each with its own observations and its own limits.",
      +      "items": {
      +        "type": "object"
      +      },
      +      "type": "array"
      +    }
      +  },
      +  "required": [
      +    "results"
      +  ],
      +  "type": "object"
      +}
  5. First observed

TDQS

A4.4/5.0
Behavior5/5

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

Annotations declare readOnlyHint=false, and the description explains precisely why: an x402 authorisation moves USDC and records a receipt, while a call without one changes nothing. It further discloses the 400 'too_many' refusal instead of silent truncation, the capability-gated 'shared' block on Analyst+, and what an empty list means. This is materially more than the annotations provide.

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?

Front-loaded with the purpose, then the differentiator, then pricing, then the readOnlyHint rationale. Every paragraph carries information, though the 'four agents stopping together' illustration and the closing receipt warning are somewhat verbose for what they add.

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?

An output schema exists, so return shape needn't be explained. The description still covers pricing model, capability gating, error behavior, interpretation caveats, and the safety rationale — everything an agent needs to decide whether and how to call it.

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% and the single parameter's constraints (1-50, mixed address forms, refusal at 51, one row per address in input order) are already written verbatim in the schema. The description restates the same limit and refusal behavior, adding little beyond the structured field.

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?

States a specific verb and resource ('Check up to fifty addresses in one call') and immediately specifies the two outputs: per-address observations plus the set-level 'shared' block. It explicitly carves out what a per-address row cannot contain, which differentiates it from counterparty_check without needing to open either schema.

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?

Gives a clear when-to-use context: when the input is your own shortlist and you want the shared-payee intersection across it. It also explains the two payment paths and the capability gate. It stops short of explicitly naming counterparty_check as the single-address alternative, so the routing is implied rather than spelled out.

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