Skip to main content
Glama

azeth_get_guardrails

Check security guardrails for smart accounts, including spending limits, token/protocol whitelists, daily spend tracking, and pending changes.

Instructions

View the guardian security configuration for a smart account.

Use this when: You want to check spending limits, token/protocol whitelists, daily spend tracking, emergency withdrawal status, or pending guardrail changes.

Returns: Full guardian state including spending limits (USD), whitelisted tokens and protocols, daily spend progress, and any pending timelock changes.

This is read-only and safe to call at any time.

Example: { "smartAccount": "me" }

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").
smartAccountNoSmart account to inspect. Accepts address, "me", "#N", or account name. Defaults to first account.

Implementation Reference

  • The handler for the azeth_get_guardrails MCP tool, which queries blockchain state for smart account security configurations like spending limits, whitelists, and pending changes.
    server.registerTool(
      'azeth_get_guardrails',
      {
        description: [
          'View the guardian security configuration for a smart account.',
          '',
          'Use this when: You want to check spending limits, token/protocol whitelists,',
          'daily spend tracking, emergency withdrawal status, or pending guardrail changes.',
          '',
          'Returns: Full guardian state including spending limits (USD), whitelisted tokens',
          'and protocols, daily spend progress, and any pending timelock changes.',
          '',
          'This is read-only and safe to call at any time.',
          '',
          'Example: { "smartAccount": "me" }',
        ].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").'),
          smartAccount: z.string().optional().describe('Smart account to inspect. Accepts address, "me", "#N", or account name. Defaults to first account.'),
        }),
      },
      async (args) => {
        let client;
        try {
          client = await createClient(args.chain);
    
          // Resolve smart account (defaults to first)
          let account: `0x${string}`;
          if (args.smartAccount) {
            try {
              account = (await resolveSmartAccount(args.smartAccount, client))!;
            } catch (resolveErr) {
              return handleError(resolveErr);
            }
          } else {
            account = await client.resolveSmartAccount();
          }
    
          const chain = resolveChain(args.chain);
          const guardianAddr = AZETH_CONTRACTS[chain].guardianModule;
    
          // Parallel reads for efficiency: guardrails, daily spend, pending changes
          const [guardrails, dailySpentUSD, pendingChange, pendingEmergency] = await Promise.all([
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'getGuardrails',
              args: [account],
            }),
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'getDailySpentUSD',
              args: [account],
            }),
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'getPendingChange',
              args: [account],
            }),
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'getPendingEmergency',
              args: [account],
            }),
          ]);
    
          // Check common token whitelists (ETH, USDC, WETH)
          const ETH = '0x0000000000000000000000000000000000000000' as `0x${string}`;
          const usdc = TOKENS[chain].USDC;
          const weth = TOKENS[chain].WETH;
    
          // Check common protocol whitelists (Azeth modules)
          const paymentAgreementModule = AZETH_CONTRACTS[chain].paymentAgreementModule;
          const reputationModule = AZETH_CONTRACTS[chain].reputationModule;
    
          const [
            ethWhitelisted,
            usdcWhitelisted,
            wethWhitelisted,
            paymentAgreementWhitelisted,
            reputationWhitelisted,
          ] = await Promise.all([
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'isTokenWhitelisted',
              args: [account, ETH],
            }),
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'isTokenWhitelisted',
              args: [account, usdc],
            }),
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'isTokenWhitelisted',
              args: [account, weth],
            }),
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'isProtocolWhitelisted',
              args: [account, paymentAgreementModule],
            }),
            client.publicClient.readContract({
              address: guardianAddr,
              abi: GuardianModuleAbi,
              functionName: 'isProtocolWhitelisted',
              args: [account, reputationModule],
            }),
          ]);
    
          // Format the Guardrails struct (6 fields from ABI)
          const g = guardrails as {
            maxTxAmountUSD: bigint;
            dailySpendLimitUSD: bigint;
            guardianMaxTxAmountUSD: bigint;
            guardianDailySpendLimitUSD: bigint;
            guardian: `0x${string}`;
            emergencyWithdrawTo: `0x${string}`;
          };
    
          const dailySpent = dailySpentUSD as bigint;
          const dailyLimit = g.dailySpendLimitUSD;
          const dailyRemaining = dailyLimit > dailySpent ? dailyLimit - dailySpent : 0n;
          const dailyPercentUsed = dailyLimit > 0n
            ? Number((dailySpent * 10000n) / dailyLimit) / 100
            : 0;
    
          // Format pending change
          const pc = pendingChange as { changeHash: `0x${string}`; executeAfter: bigint; exists: boolean };
          const pe = pendingEmergency as { token: `0x${string}`; executeAfter: bigint; exists: boolean };
    
          const now = BigInt(Math.floor(Date.now() / 1000));
    
          return success({
            account,
            spendingLimits: {
              maxTransactionUSD: `$${formatUnits(g.maxTxAmountUSD, 18)}`,
              dailySpendLimitUSD: `$${formatUnits(dailyLimit, 18)}`,
              dailySpentUSD: `$${formatUnits(dailySpent, 18)}`,
              dailyRemainingUSD: `$${formatUnits(dailyRemaining, 18)}`,
              dailyPercentUsed: `${dailyPercentUsed.toFixed(1)}%`,
            },
            guardianLimits: {
              guardianMaxTransactionUSD: `$${formatUnits(g.guardianMaxTxAmountUSD, 18)}`,
              guardianDailySpendLimitUSD: `$${formatUnits(g.guardianDailySpendLimitUSD, 18)}`,
            },
            guardian: g.guardian,
            emergencyWithdrawTo: g.emergencyWithdrawTo,
            tokenWhitelist: {
              ETH: ethWhitelisted as boolean,
              USDC: usdcWhitelisted as boolean,
              WETH: wethWhitelisted as boolean,
            },
            protocolWhitelist: {
              PaymentAgreementModule: paymentAgreementWhitelisted as boolean,
              ReputationModule: reputationWhitelisted as boolean,
            },
            pendingGuardrailChange: pc.exists ? {
              changeHash: pc.changeHash,
              executeAfter: new Date(Number(pc.executeAfter) * 1000).toISOString(),
              readyIn: pc.executeAfter > now
                ? `${Math.ceil(Number(pc.executeAfter - now) / 60)} minutes`
                : 'READY to execute',
            } : null,
            pendingEmergencyWithdrawal: pe.exists ? {
              token: pe.token,
              executeAfter: new Date(Number(pe.executeAfter) * 1000).toISOString(),
              readyIn: pe.executeAfter > now
                ? `${Math.ceil(Number(pe.executeAfter - now) / 60)} minutes`
                : 'READY to execute',
            } : null,
          });
        } 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`); }
        }
      },
    );

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