Skip to main content
Glama

azeth_get_agreement

View payment agreement details including status, payment history, and next execution time to inspect terms before executing or cancelling.

Instructions

View full details of a payment agreement including status, payment history, and next execution time.

Use this when: You want to inspect an agreement before executing or cancelling it, verify terms after creation, or check how much has been paid so far.

Returns: Complete agreement details with human-readable amounts, status, and timing.

Note: This is a read-only on-chain query. No gas or private key required for the query itself, but account resolution may need your key if using "me" or "#N".

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chainNoTarget chain. Defaults to AZETH_CHAIN env var or "baseSepolia". Accepts "base", "baseSepolia", "ethereumSepolia", "ethereum" (and aliases like "base-sepolia", "eth-sepolia", "sepolia", "eth", "mainnet").
accountYesThe payer smart account: Ethereum address, participant name, "me", or "#N".
agreementIdYesThe agreement ID to query.

Implementation Reference

  • The handler for `azeth_get_agreement` which retrieves agreement details from on-chain data.
      async (args) => {
        let client;
        try {
          client = await createClient(args.chain);
          const chain = resolveChain(args.chain);
    
          let accountResolved;
          try {
            accountResolved = await resolveAddress(args.account, client);
          } catch (resolveErr) {
            return handleError(resolveErr);
          }
    
          const account = accountResolved.address;
          const agreementId = BigInt(args.agreementId);
    
          // Single RPC call: agreement + executability + isDue + nextExecutionTime + count
          let data;
          try {
            data = await client.getAgreementData(agreementId, account);
          } catch {
            return error('INVALID_INPUT', `Agreement #${args.agreementId} not found for account ${account}.`, 'Check the agreement ID with azeth_list_agreements.');
          }
    
          const { agreement, executable, reason, isDue: contractIsDue, nextExecutionTime: nextExecTime } = data;
          const decimals = tokenDecimals(agreement.token, chain);
          const tokenSymbol = resolveTokenSymbol(agreement.token, chain);
          const now = BigInt(Math.floor(Date.now() / 1000));
          const status = deriveStatus(agreement, now);
          const intervalSecs = Number(agreement.interval);
    
          // Timing
          const lastExecutedAt = agreement.lastExecuted === 0n
            ? null
            : new Date(Number(agreement.lastExecuted) * 1000).toISOString();
    
          let nextExecutionTime: string;
          let nextExecutionIn: string;
          let isDue = contractIsDue;
          let canExecute = executable;
          let canExecuteReason: string | undefined;
    
          if (status !== 'active') {
            nextExecutionTime = 'N/A';
            nextExecutionIn = `N/A (${status})`;
            canExecute = false;
            isDue = false;
          } else {
            nextExecutionTime = new Date(Number(nextExecTime) * 1000).toISOString();
            const nowSecs = Math.floor(Date.now() / 1000);
            const diff = Number(nextExecTime) - nowSecs;
            if (diff <= 0) {
              nextExecutionIn = `now (overdue by ${formatOverdue(-diff)})`;
              isDue = true;
            } else {
              nextExecutionIn = formatCountdown(diff);
            }
    
            if (!executable && reason) {
              canExecuteReason = reason;
            }
          }
    
          // Payee name resolution
          const payeeName = await lookupPayeeName(client, agreement.payee);
    
          return success({
            agreementId: args.agreementId.toString(),
            account,
            payee: agreement.payee,
            ...(payeeName ? { payeeName } : {}),
            token: agreement.token,
            tokenSymbol,
            status,
            // Payment terms
            amountPerInterval: formatUnits(agreement.amount, decimals),
            intervalSeconds: intervalSecs,
            intervalHuman: formatInterval(intervalSecs),
            // Execution state
            executionCount: agreement.executionCount.toString(),
            maxExecutions: agreement.maxExecutions === 0n ? 'unlimited' : agreement.maxExecutions.toString(),
            totalPaid: formatUnits(agreement.totalPaid, decimals),
            totalCap: agreement.totalCap === 0n ? 'unlimited' : formatUnits(agreement.totalCap, decimals),
            remainingBudget: agreement.totalCap === 0n
              ? 'unlimited'
              : formatUnits(agreement.totalCap - agreement.totalPaid, decimals),
            // Timing
            lastExecutedAt,
            nextExecutionTime,
            nextExecutionIn,
            expiresAt: agreement.endTime === 0n ? 'never' : new Date(Number(agreement.endTime) * 1000).toISOString(),
            // Checks
            isDue,
            canExecute,
            ...(canExecuteReason ? { canExecuteReason } : {}),
          });
        } catch (err) {
          return handleError(err);
        } finally {
          try { await client?.destroy(); } catch (e) { process.stderr.write(`[azeth-mcp] destroy error: ${e instanceof Error ? e.message : String(e)}\n`); }
        }
      },
    );
  • Registration of the `azeth_get_agreement` tool.
    server.registerTool(
      'azeth_get_agreement',
      {
        description: [
          'View full details of a payment agreement including status, payment history, and next execution time.',
          '',
          'Use this when: You want to inspect an agreement before executing or cancelling it,',
          'verify terms after creation, or check how much has been paid so far.',
          '',
          'Returns: Complete agreement details with human-readable amounts, status, and timing.',
          '',
          'Note: This is a read-only on-chain query. No gas or private key required for the query itself,',
          'but account resolution may need your key if using "me" or "#N".',
        ].join('\n'),
        inputSchema: z.object({
          chain: z.string().optional().describe('Target chain. Defaults to AZETH_CHAIN env var or "baseSepolia". Accepts "base", "baseSepolia", "ethereumSepolia", "ethereum" (and aliases like "base-sepolia", "eth-sepolia", "sepolia", "eth", "mainnet").'),
          account: z.string().describe('The payer smart account: Ethereum address, participant name, "me", or "#N".'),
          agreementId: z.coerce.number().int().min(0).describe('The agreement ID to query.'),
        }),
      },

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/azeth-protocol/mcp-azeth'

If you have feedback or need assistance with the MCP directory API, please join our Discord server