{
  "name": "Testril",
  "description": "Ormi's on-demand blockchain data service for AI agents. Request a metric and scope, receive a per-request quote, then retrieve paid data and verify its provenance.",
  "mcp_endpoint": "https://dev.testril.ai/mcp",
  "documentation_url": "https://testril.si/agents/",
  "authentication": "Tool discovery and free inspection need no API key. Paid calls require a payment-capable MCP host to attach a signed x402 v2 payload after operator authorization.",
  "payment": {
    "protocol": "x402 v2 over MCP",
    "pricing_model": "Metered, request-specific quotes; no fixed price or selectable price tiers. An exact quoted charge may use any settlement scheme offered in its accepts rows.",
    "amount": "Quoted for the specific request. Read the returned PaymentRequired accepts rows and quote before paying.",
    "network": "Read from the actual accepts row; do not assume a fixed network."
  },
  "instructions": "Connect to the MCP endpoint with a Streamable HTTP client and read the server instructions and tools/list schemas. This card points to the development deployment. Call health_check for process and configured-chain diagnostics; call inspect with subject functions, chains, or pricing to discover the live catalog and published meter rates. The final charge is not fixed by this card or the rate table. It depends on the exact bound Function, scope, and window.\n\nUse ask to select an existing Function from a metric request, or bind a known Function to explicit chain and parameter scope. These steps establish a Bound Function identity; they do not deliver data. Inspect the Bound Function and chain head before choosing a half-open block or UTC period window. Call materialize only for coverage that is missing, then inspect the returned job until it finishes. Call read to retrieve metric rows and provenance to expand the source block evidence. claim_rewards takes the nft id from inspect subject:nft. The server advertises nine tools today; discover their current schemas rather than treating this summary as a static contract.\n\nAn unpaid materialize or read call returns an MCP error result with x402 PaymentRequired in structuredContent/content[0] and the quote {quote_id, amount, lines} in content[1]. Show the operator the exact amount and scope, confirm authorization, and let the payment-capable host retry the identical call with the signed payload in _meta[\"x402/payment\"]. The paid result carries _meta[\"x402/payment-response\"]. There is no separate pay tool or payment_id argument. Do not send a private key or invent an amount. The quote expires after 120 seconds. The same spent payment or x402 payment-identifier can retrieve the purchase again without a second charge; a different request using that identifier is refused as payment_identifier_conflict. If payment recovery is pending, retry the original paid call and never sign a replacement. Some small requests offer batch settlement with a minimum deposit larger than the individual quote, so authorize the full deposit. A paid materialize answers materializing with a job handle; a receipt alone is not completed data. Discover each Function's live row schema and use the actual quote for the current request.",
  "constraints": [
    "Development MCP endpoint: https://dev.testril.ai/mcp. This card does not establish production availability.",
    "Configured computation chains, payment networks, prices, and recipients are deployment and quote specific.",
    "Quote lifetime is 120 seconds; payment and execution must start before expiry.",
    "No uptime or rate-limit SLA is asserted here."
  ],
  "tools": [
    {"name": "health_check", "description": "Check process health, version, configured chain IDs, and catalog counts.", "pricing": {"scheme": "free"}},
    {"name": "inspect", "description": "Inspect catalog Functions, chains, bound scope, jobs, channels, and meter rates without reading metric rows.", "pricing": {"scheme": "free"}},
    {"name": "bind", "description": "Bind an existing Function to a chain and parameter scope; returns a stable Bound Function ID.", "pricing": {"scheme": "free"}},
    {"name": "ask", "description": "Select and bind a catalog Function from a metric request; may request missing parameters or window.", "pricing": {"scheme": "free"}},
    {"name": "materialize", "description": "Compute missing data for a requested window after authorized x402 payment. The amount and settlement scheme come from this call's quote and accepts rows; inspect subject:pricing returns meter rates, not price tiers or a final charge.", "pricing": {"variable": true, "see_tool": "inspect", "quote_on_call": true}},
    {"name": "read", "description": "Return metric rows from materialized coverage after authorized x402 payment. The amount and settlement scheme come from this call's quote and accepts rows; inspect subject:pricing returns meter rates, not price tiers or a final charge.", "pricing": {"variable": true, "see_tool": "inspect", "quote_on_call": true}},
    {"name": "provenance", "description": "Expand a result's source block evidence and digest for verification.", "pricing": {"scheme": "free"}},
    {"name": "stop", "description": "Cancel an eligible in-flight materialization and refund its unspent part to the claim-right holder.", "pricing": {"scheme": "free"}},
    {"name": "claim_rewards", "description": "Claim an eligible claim-right NFT's accumulated USDC rewards to its current owner on the NFT's recorded network; no payout-network selector.", "pricing": {"scheme": "free"}}
  ]
}
