get_bridge_quote
Obtain a quote for transferring the same token between blockchain networks, including estimated output amount, fees breakdown, and time estimate.
Instructions
Get a quote for bridging the same token from one chain to another (e.g. ETH on Ethereum → ETH on Base). Returns estimated output amount, fees breakdown, and time estimate. Use get_swap_quote instead if you want to change the token type.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| originChainId | Yes | Source chain ID (e.g. 1 for Ethereum). | |
| destinationChainId | Yes | Destination chain ID (e.g. 8453 for Base). | |
| currency | Yes | Token address to bridge. Use "0x0000000000000000000000000000000000000000" for native ETH. | |
| amount | Yes | Amount to bridge in the token's smallest unit (wei for ETH). Example: "1000000000000000000" for 1 ETH. | |
| sender | Yes | Sender wallet address. | |
| recipient | No | Recipient wallet address. Defaults to sender if not provided. |
Implementation Reference
- src/tools/get-bridge-quote.ts:6-102 (handler)Main implementation of the get_bridge_quote tool. Contains the registration with McpServer, input schema definition (lines 10-36), and the async handler function (lines 37-100) that fetches a quote using getQuote(), formats the response, builds a deeplink URL, and returns structured content with summary, JSON details, and resource link.
export function register(server: McpServer) { server.tool( "get_bridge_quote", "Get a quote for bridging the same token from one chain to another (e.g. ETH on Ethereum → ETH on Base). Returns estimated output amount, fees breakdown, and time estimate. Use get_swap_quote instead if you want to change the token type.", { originChainId: z .number() .describe("Source chain ID (e.g. 1 for Ethereum)."), destinationChainId: z .number() .describe("Destination chain ID (e.g. 8453 for Base)."), currency: z .string() .describe( 'Token address to bridge. Use "0x0000000000000000000000000000000000000000" for native ETH.' ), amount: z .string() .describe( "Amount to bridge in the token's smallest unit (wei for ETH). Example: \"1000000000000000000\" for 1 ETH." ), sender: z .string() .describe("Sender wallet address."), recipient: z .string() .optional() .describe( "Recipient wallet address. Defaults to sender if not provided." ), }, async ({ originChainId, destinationChainId, currency, amount, sender, recipient }) => { const quote = await getQuote({ user: sender, originChainId, destinationChainId, originCurrency: currency, destinationCurrency: currency, amount, recipient, }); const { details, fees } = quote; const summary = `Bridge ${details.currencyIn.amountFormatted} ${details.currencyIn.currency.symbol} (chain ${originChainId}) → ${details.currencyOut.amountFormatted} ${details.currencyOut.currency.symbol} (chain ${destinationChainId}). Total fees: $${fees.relayer.amountUsd}. ETA: ~${details.timeEstimate}s.`; const deeplinkUrl = await buildRelayAppUrl({ destinationChainId, fromChainId: originChainId, fromCurrency: currency, toCurrency: currency, amount: details.currencyIn.amountFormatted, toAddress: recipient || sender, }); const content: Array<Record<string, unknown>> = [ { type: "text", text: summary }, { type: "text", text: JSON.stringify( { amountIn: details.currencyIn.amountFormatted, amountOut: details.currencyOut.amountFormatted, amountInUsd: details.currencyIn.amountUsd, amountOutUsd: details.currencyOut.amountUsd, fees: { gas: { formatted: fees.gas.amountFormatted, usd: fees.gas.amountUsd }, relayer: { formatted: fees.relayer.amountFormatted, usd: fees.relayer.amountUsd }, }, totalImpact: details.totalImpact, timeEstimateSeconds: details.timeEstimate, rate: details.rate, relayAppUrl: deeplinkUrl ?? undefined, }, null, 2 ), }, ]; if (deeplinkUrl) { content.push({ type: "resource_link", uri: deeplinkUrl, name: "Execute bridge on Relay", description: "Open the Relay app to sign and execute this bridge", mimeType: "text/html", }); content.push({ type: "text", text: `To execute this bridge, open the Relay app: ${deeplinkUrl}`, }); } return { content }; } ); } - src/index.ts:6-6 (registration)Import statement for get_bridge_quote tool registration.
import { register as registerGetBridgeQuote } from "./tools/get-bridge-quote.js"; - src/index.ts:22-22 (registration)Registration of get_bridge_quote tool with the MCP server.
registerGetBridgeQuote(server); - src/relay-api.ts:212-220 (helper)Helper function getQuote() that makes a POST request to the Relay API /quote/v2 endpoint. Accepts QuoteRequest parameters and returns QuoteResponse with fees, details, steps, and time estimate.
export async function getQuote(params: QuoteRequest): Promise<QuoteResponse> { return relayApi<QuoteResponse>("/quote/v2", { method: "POST", body: { ...params, tradeType: params.tradeType || "EXACT_INPUT", }, }); } - src/deeplink.ts:24-44 (helper)Helper function buildRelayAppUrl() that constructs a Relay app deeplink URL for executing the bridge. Maps chain IDs to chain names and builds a URL with query parameters for fromChainId, currencies, amount, and toAddress.
export async function buildRelayAppUrl( params: DeeplinkParams ): Promise<string | null> { const nameMap = await getChainNameMap(); const chainName = nameMap.get(params.destinationChainId); if (!chainName) return null; const url = new URL(`https://relay.link/bridge/${chainName}`); if (params.fromChainId !== undefined) url.searchParams.set("fromChainId", String(params.fromChainId)); if (params.fromCurrency) url.searchParams.set("fromCurrency", params.fromCurrency); if (params.toCurrency) url.searchParams.set("toCurrency", params.toCurrency); if (params.amount) url.searchParams.set("amount", params.amount); if (params.toAddress) url.searchParams.set("toAddress", params.toAddress); if (params.tradeType) url.searchParams.set("tradeType", params.tradeType); return url.toString(); }