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.'),
        }),
      },
Behavior5/5

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

Comprehensive disclosure appropriate for zero annotations: explicitly states 'read-only on-chain query,' gas requirements ('no gas'), and authentication needs ('no private key required...but account resolution may need your key'). Also clarifies return characteristics ('human-readable amounts') and specific account syntax caveats.

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

Conciseness5/5

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

Well-structured with clear sections (main description, Use this when, Returns, Note). Front-loaded with core action. Every sentence conveys unique operational guidance; no redundancy with schema or sibling tool names.

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?

Complete for a read-only query tool: describes return value contents ('Complete agreement details with human-readable amounts') despite lack of output schema, covers blockchain-specific concerns (gas, keys, on-chain nature), and contextualizes within the broader agreement lifecycle (creation→inspection→execution/cancellation).

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 baseline is 3. Description adds value by explaining security implications for specific account parameter values ('me' or '#N' require key for resolution), providing critical semantic context beyond the schema's type description.

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?

Excellent specificity: 'View full details of a payment agreement' provides clear verb+resource, and enumerates specific data points (status, payment history, next execution time). Clearly distinguishes from sibling tools like azeth_execute_agreement and azeth_cancel_agreement by emphasizing inspection/verification rather than mutation.

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

Usage Guidelines5/5

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

Exemplary explicit guidelines under 'Use this when:' covering three distinct scenarios (pre-execution inspection, post-creation verification, payment history checks). Directly references sibling operations 'executing or cancelling' to establish clear selection criteria vs state-changing alternatives.

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

Install Server

Other Tools

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