Skip to main content
Glama

Prepare a rebalancer config update

prepare_config
Read-only

[DEPRECATED] Build the signing hash for updating a wallet's rebalancer configuration (which pools/protocols/chains it's allowed to move funds into), without signing anything. Computes keccak256(abi.encode(managerAddress, protocolIds, poolAddresses, domainIds, spendingCapRaw)) server-side — sign the returned hashToSign with personal_sign over its raw 32 bytes (not the UTF-8 text of the hex string) and pass the signature to submit_config. Refuses to build a config that would drop a pool you still hold a nonzero balance in — withdraw from it first (prepare_withdrawal) and retry. Also refuses an invalid spendingCapRaw (see its own field description for the exact rules), a non-null collateralExposure with no Aave pool included, containing an untracked symbol, or where no requested Aave pool's live TVL meets requiredTvl, any (domainId, protocolId, poolAddress) tuple that doesn't match a real pool in the current catalog for this token (see list_pools), or a config where every requested pool is blacklisted (see list_pools' blacklisted field) — a deposit under such a config would have no eligible destination and fail later, well after signing — rather than building a hash for it. For a smart-contract wallet: there is no single chain for this signature — the backend derives candidate chains straight from domainIds and requires the SAME signature to independently pass ERC-1271/ERC-6492 verification on EVERY chain named in domainIds, not just one; if the wallet doesn't have (deployed, or via ERC-6492 counterfactual deployment) a valid signer on all of them, the whole update is rejected. That signature must also be cross-chain transferable — supporting ERC-6492 counterfactual deployment does not by itself guarantee that. Some ERC-6492-compliant wallets intentionally bind their signature to a single network domain and are not cross-chain transferable — e.g. Coinbase's Smart Wallet (Base Smart Wallet) supports ERC-6492 but scopes its signature to one chain, so it does not support cross-chain signatures. For a wallet like that, keep domainIds restricted to that single chain (see domainIds' own field description) and sign on that exact chain, rather than mixing pools across chains. An EOA is unaffected (one ECDSA signature covers every chain). Even with a valid signature, submit_config can still be rejected with a 409 if a rebalance or deposit is currently in progress for this wallet+token, or (USDC only) a funding-cap refill is in progress — there is no read-only endpoint to check that ahead of time, so it is NOT pre-validated here; treat a 409 there as temporary and retry later (the error body includes a retryAfterSeconds hint), not as a problem with the signature itself. Rate limited to 5 calls/minute per caller, no more than one call every 12s.

Input Schema

NameRequiredDescriptionDefault
tokenYesToken symbol this config applies to, e.g. USDC, USDT, MUSD, RLUSD, USDG, USDE, PYUSD.
domainIdsYesChain domain IDs, one per poolAddresses entry, from list_pools' signData.domainId. Max 200 entries. For a smart-contract wallet, every distinct chain named here must independently verify the SAME signature — the standards supported for smart-wallet signature verification are ERC-1271 and ERC-6492 (counterfactual deployment). Supporting ERC-6492 is not the same as producing a cross-chain-transferable signature: some ERC-6492-compliant wallets intentionally bind their signature to a single network domain, so the same signature will never verify on a second chain regardless of 6492 support. Coinbase's Smart Wallet (Base Smart Wallet) is an example — it does support ERC-6492, but its signatures are domain-bound by design, so it does not support cross-chain signatures. For a wallet like that, keep domainIds single-chain — e.g. all Base, or all Ethereum, matching whichever chain the wallet's signature is scoped to — and sign the hashToSign with that wallet's signer on that exact chain; do not mix pools from other chains into the same config, that combination will always fail verification.
protocolIdsYes0=Aave, 1=Morpho, 2=Euler, 3=AaveV4 — one entry per poolAddresses/domainIds entry, from list_pools' signData.protocolId. Pass only the exact set of (domainId, protocolId, poolAddress) pools you intend to allow, with no duplicate entries. Max 200 entries.
requiredTvlNoMinimum pool TVL in USD required for a pool to be eligible as a rebalance target — pools below this are skipped when the rebalancer picks where to move funds. 0 (default if omitted) disables the filter. Max 500000000. Accepts a number or a numeric string, and is always returned/forwarded as a string to preserve exact decimal precision (the backend stores this as an unrestricted-precision decimal, and get_config's own response already serializes it as a string for the same reason — pass that value straight through, it is never converted through a JS number here, which would silently round a high-precision value). When reconfiguring an existing signed config, copy this wallet's current value from get_config rather than omitting it, or you'll silently reset it to 0 (no floor).
poolAddressesYesPool contract addresses to allow, from list_pools' signData.poolAddress. Max 200 entries.
walletAddressYesEVM wallet address (0x-prefixed, 40 hex chars). Any casing is accepted — it is normalized to its EIP-55 checksum before being forwarded upstream.
spendingCapRawNoRaw units, USDC only (must be "0"/null/omitted for every other token). "0" means this feature is off (the default if omitted or null — get_config's own response serializes it as null, pass that straight through). A nonzero value turns it on and is the TARGET BALANCE MetaLend automatically keeps topped up in the wallet's OWN address (not the rebalancer contract) as Aave aUSDC + native USDC on Linea combined — it funds a card (e.g. MetaMask card) tied to this wallet that spends directly from that Linea balance. It is not a spending/deposit/withdrawal ceiling and does not limit how much can be deposited or withdrawn elsewhere. MetaLend tops the wallet back up toward this target automatically (pulling from the rebalancer's own positions, bridging cross-chain if needed) on a weekly cycle and whenever the wallet makes a fresh USDC deposit — not instantly on every call. It also biases a USDC deposit whose source chain is Linea itself to land in the Linea Aave pool first (the cheapest source for that top-up) while the wallet's own Linea balance is still under this target. Must match exactly between prepare_config and submit_config. If set nonzero, must be at least 1000000 (1 USDC) and the config must include the Aave pool on Linea.
includeRewardsApyNoWhether reward-token (e.g. Merkle) APY counts toward the total-APY comparison used to pick the best pool to rebalance into — false restricts the comparison to native lending APY only. Defaults to true if omitted. When reconfiguring an existing signed config, copy this wallet's current value from get_config rather than omitting it, or you'll silently reset it.
collateralExposureNoWhitelist of collateral asset symbols — applies only to Morpho vault selection; a vault is excluded from rebalancing if its own tracked collateral exposure includes any symbol not in this list. Each symbol must be one MetaLend actually tracks exposure for on at least one Morpho vault (see list_pools' collateralExposure values) — rejected here, before signing, otherwise. null (default if omitted) disables the filter entirely — an empty array is rejected, use null instead. Setting this to a non-null list also requires the config to include at least one Aave pool (rejected here, before signing, if none is present) whose live TVL (see list_pools' poolTvl) also meets requiredTvl — also rejected here, before signing, if none of the requested Aave pools currently qualify. When reconfiguring an existing signed config, copy this wallet's current value from get_config rather than omitting it, or you'll silently disable this filter.
requiredLiquidityMultiplierNoRequires a candidate pool's available liquidity to be at least this multiplier times the deposit amount (USD) before it's eligible as a rebalance target — a liquidity safety margin, not a percentage. 0 (default if omitted) disables the check. Max 1000. Accepts a number or a numeric string, and is always returned/forwarded as a string to preserve exact decimal precision (the backend stores this as an unrestricted-precision decimal, and get_config's own response already serializes it as a string for the same reason — pass that value straight through, it is never converted through a JS number here, which would silently round a high-precision value). When reconfiguring an existing signed config, copy this wallet's current value from get_config rather than omitting it, or you'll silently reset it to 0 (no margin required).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / protocolIds / description
      Previous value: -"0=Aave, 1=Morpho, 2=Euler — one entry per poolAddresses/domainIds entry, from list_pools' signData.protocolId. Pass only the exact set of (domainId, protocolId, poolAddress) pools you intend to allow, with no duplicate entries. Max 200 entries."New value: +"0=Aave, 1=Morpho, 2=Euler, 3=AaveV4 — one entry per poolAddresses/domainIds entry, from list_pools' signData.protocolId. Pass only the exact set of (domainId, protocolId, poolAddress) pools you intend to allow, with no duplicate entries. Max 200 entries."
  2. First observed

TDQS

A4.5/5.0
Behavior5/5

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

Far exceeds the annotations (readOnlyHint/openWorldHint/destructiveHint), which only say this call mutates nothing. The description discloses the exact hashing scheme (keccak256 of the abi-encoded tuple), that signing must be personal_sign over raw 32 bytes and not the hex string, the refusal invariants (nonzero-balance pool, invalid spendingCapRaw, unmapped pool tuples, all-blacklisted config), cross-chain verification semantics for ERC-1271/ERC-6492, and the rate limit (5/min, one per 12s). This is exactly the behavioral context annotations cannot carry.

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

Conciseness3/5

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

The core purpose is front-loaded, but the body is a single ~600-word block of run-on, em-dash-chained sentences mixing refusals, cross-chain verification theory, a Coinbase Smart Wallet example, and rate limits. Much of the content is load-bearing, yet the density and lack of structure make it hard to scan.

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?

For a 10-parameter, no-output-schema, high-stakes signing tool, the description covers what is returned (hashToSign), what the caller must do with it, which failures are pre-validated here versus deferred to submit_config, and the 409 retryAfterSeconds behavior. Nothing needed to invoke it correctly is missing.

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 the baseline would be 3, but the description adds cross-parameter semantics the schema does not consolidate: nonzero spendingCapRaw requiring an Aave-on-Linea pool, collateralExposure requiring an Aave pool whose live TVL meets requiredTvl, and the fact that pooling domainIds across chains always fails for domain-bound smart wallets. It also states the exact encoding order of the five tuple fields.

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+resource: 'Build the signing hash for updating a wallet's rebalancer configuration... without signing anything.' It explicitly scopes the side-effect-free nature and names the downstream sibling (submit_config) that consumes the output, plus prepare_withdrawal and list_pools as related tools. An agent can distinguish this from submit_config without opening 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 rich when-to-use/when-not guidance (build-then-sign-then-submit flow, EOA vs smart-contract wallet handling, retry-later on 409 rather than treating it as a signature problem). However, despite the explicit [DEPRECATED] tag, it never says what to use instead or whether the tool should still be called — a notable gap in routing guidance for a deprecated tool.

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.