Skip to main content
Glama

execute_bridge

Generate unsigned transactions and signatures for cross-chain token transfers or swaps via Relay Protocol. Returns all required steps including approvals and deposits for ERC-20 tokens.

Instructions

Get a quote and unsigned transactions for a bridge or swap via Relay. Returns ALL steps required to complete the transfer.

For ERC-20 tokens (like USDC), there are typically TWO steps:

  1. approve — An ERC-20 approval transaction allowing Relay to spend the token.

  2. deposit — The actual bridge/swap transaction.

For native tokens (ETH), there is usually just ONE step:

  1. deposit — The bridge/swap transaction.

Some routes may also include a "signature" step (EIP-712 signing instead of a transaction).

Each step has a "kind" field:

  • "transaction" → must be signed and broadcast via eth_sendTransaction

  • "signature" → must be signed via eth_signTypedData_v4, then POSTed to the Relay API

After calling this tool, pass ALL the returned steps to the wallet tool with action "execute" to sign and submit them in order. The wallet tool handles the full multi-step flow automatically.

If a wallet is connected via the wallet tool, the sender defaults to the connected address. Returns a requestId for tracking status via get_transaction_status.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
originChainIdYesSource chain ID.
destinationChainIdYesDestination chain ID.
originCurrencyYesOrigin token address. "0x0000000000000000000000000000000000000000" for native.
destinationCurrencyYesDestination token address. "0x0000000000000000000000000000000000000000" for native.
amountYesAmount in the origin token's smallest unit (wei).
senderNoSender wallet address. If omitted and a wallet is connected via the wallet tool, the connected address is used.
recipientNoRecipient wallet address. Defaults to sender.

Implementation Reference

  • The main handler function that executes the execute_bridge tool. It resolves the sender address from wallet session if not provided, calls the Relay API to get a quote, validates that steps exist, extracts the requestId, and returns formatted response with steps, fees, and execution hints.
    async ({
      originChainId,
      destinationChainId,
      originCurrency,
      destinationCurrency,
      amount,
      sender,
      recipient,
    }) => {
      // Resolve sender from connected wallet if not provided
      const walletState = getSessionInfo();
      const resolvedSender = sender || walletState.address;
    
      if (!resolvedSender) {
        return {
          content: [
            {
              type: "text",
              text: 'Error: No sender address provided and no wallet connected. Either pass a sender address or connect a wallet first using the wallet tool with action "pair".',
            },
          ],
          isError: true,
        };
      }
    
      const quote = await getQuote({
        user: resolvedSender,
        originChainId,
        destinationChainId,
        originCurrency,
        destinationCurrency,
        amount,
        recipient,
      });
    
      if (!quote.steps || quote.steps.length === 0) {
        return {
          content: [
            {
              type: "text",
              text: "Error: Quote returned no executable steps. The route may not be available.",
            },
          ],
          isError: true,
        };
      }
    
      const { details, fees } = quote;
    
      // Find the requestId from the deposit step (or last step)
      const depositStep = quote.steps.find((s) => s.id === "deposit") || quote.steps[quote.steps.length - 1];
      const requestId = depositStep.requestId;
    
      // Build step summaries
      const stepSummaries = quote.steps.map((step, i) => {
        return `Step ${i + 1}: ${step.action} (${step.kind}, id: ${step.id})`;
      });
    
      const walletHint = walletState.connected
        ? ' A wallet is connected — call wallet with action "execute" and pass the steps array to sign and submit all transactions automatically.'
        : " Sign and broadcast each transaction in order, polling the check endpoint between steps, then use get_transaction_status with the requestId to track completion.";
    
      const summary = `Ready to execute: ${details.currencyIn.amountFormatted} ${details.currencyIn.currency.symbol} (chain ${originChainId}) → ${details.currencyOut.amountFormatted} ${details.currencyOut.currency.symbol} (chain ${destinationChainId}).\n\nSteps required (${quote.steps.length}):\n${stepSummaries.join("\n")}${walletHint}`;
    
      return {
        content: [
          { type: "text", text: summary },
          {
            type: "text",
            text: JSON.stringify(
              {
                steps: quote.steps,
                requestId,
                sender: resolvedSender,
                amountIn: details.currencyIn.amountFormatted,
                amountOut: details.currencyOut.amountFormatted,
                fees: {
                  gas: fees.gas.amountUsd,
                  relayer: fees.relayer.amountUsd,
                },
                timeEstimateSeconds: details.timeEstimate,
              },
              null,
              2
            ),
          },
        ],
      };
    }
  • Zod schema defining the input parameters for execute_bridge tool: originChainId, destinationChainId, originCurrency, destinationCurrency, amount (required), and optional sender and recipient addresses.
    originChainId: z.number().describe("Source chain ID."),
    destinationChainId: z.number().describe("Destination chain ID."),
    originCurrency: z
      .string()
      .describe(
        'Origin token address. "0x0000000000000000000000000000000000000000" for native.'
      ),
    destinationCurrency: z
      .string()
      .describe(
        'Destination token address. "0x0000000000000000000000000000000000000000" for native.'
      ),
    amount: z
      .string()
      .describe("Amount in the origin token's smallest unit (wei)."),
    sender: z
      .string()
      .optional()
      .describe(
        "Sender wallet address. If omitted and a wallet is connected via the wallet tool, the connected address is used."
      ),
    recipient: z
      .string()
      .optional()
      .describe("Recipient wallet address. Defaults to sender."),
  • src/index.ts:9-9 (registration)
    Import statement importing the register function for execute_bridge tool from tools/execute-bridge.js
    import { register as registerExecuteBridge } from "./tools/execute-bridge.js";
  • src/index.ts:25-25 (registration)
    Registration call that registers the execute_bridge tool with the MCP server instance.
    registerExecuteBridge(server);
  • Helper function getQuote that makes a POST request to the Relay API's /quote/v2 endpoint to retrieve bridge/swap quotes including steps, fees, and details.
    export async function getQuote(params: QuoteRequest): Promise<QuoteResponse> {
      return relayApi<QuoteResponse>("/quote/v2", {
        method: "POST",
        body: {
          ...params,
          tradeType: params.tradeType || "EXACT_INPUT",
        },
      });
    }

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/pedromcunha/relay-mcp'

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