Skip to main content
Glama

LayerZero OFT MCP Server

by thomasfevre

bridge-oft

Transfer OFT tokens across blockchain networks using LayerZero protocol. Specify token address, amount, source and destination chains, and receiver address to execute cross-chain bridging.

Instructions

Bridges OFT tokens from one chain to another using LayerZero.

Input Schema

NameRequiredDescriptionDefault
amountYesThe amount of tokens to bridge (e.g., '100').
extraOptionsNoExtra options for LayerZero message execution (default: '0x').0x
fromChainYesThe source chain name.
receiverAddressYesThe address to receive tokens on the destination chain.
toChainYesThe destination chain name.
tokenAddressYesThe address of the OFT contract on the source chain.

Input Schema (JSON Schema)

{ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "amount": { "description": "The amount of tokens to bridge (e.g., '100').", "type": "string" }, "extraOptions": { "default": "0x", "description": "Extra options for LayerZero message execution (default: '0x').", "type": "string" }, "fromChain": { "description": "The source chain name.", "enum": [ "ArbitrumSepolia", "baseSepolia" ], "type": "string" }, "receiverAddress": { "description": "The address to receive tokens on the destination chain.", "type": "string" }, "toChain": { "description": "The destination chain name.", "enum": [ "ArbitrumSepolia", "baseSepolia" ], "type": "string" }, "tokenAddress": { "description": "The address of the OFT contract on the source chain.", "type": "string" } }, "required": [ "tokenAddress", "amount", "fromChain", "toChain", "receiverAddress" ], "type": "object" }

Implementation Reference

  • The core handler function for the 'bridge-oft' tool. It loads the OFT ABI, validates inputs, gets signers and network configs from utils, creates the contract instance, prepares LayerZero send parameters, quotes the fee, executes the send transaction, and returns the transaction details.
    async (params: z.infer<typeof bridgeOftParams>) => { try { const MyOFT = JSON.parse(await readFile(oftPath, "utf8")); const OFT_ABI = MyOFT.abi; if ( OFT_ABI === "ABI_PLACEHOLDER" || OFT_ABI === undefined || OFT_ABI.length === 0 ) { return { content: [ { type: "text", text: "Error: Placeholder ABI detected. Please replace OFT_ABI in layerzero-mcp.ts with your actual contract ABI to interact with existing contracts.", }, ], isError: true, }; } if (params.fromChain === params.toChain) { return { content: [ { type: "text", text: "Error: Source and destination chains cannot be the same.", }, ], isError: true, }; } const signer = await getSigner(params.fromChain); const fromNetworkConfig = getNetworkConfig(params.fromChain); const toNetworkConfig = getNetworkConfig(params.toChain); // Assuming 18 decimals for OFT amounts. Make this configurable if needed. const amountDecimals = 18; const amountBigInt = parseUnits(params.amount, amountDecimals); const contract = new Contract(params.tokenAddress, OFT_ABI, signer); const formattedReceiverAddress = formatAddressForLayerZero( params.receiverAddress ); const sendParam = { dstEid: toNetworkConfig.lzEid, to: formattedReceiverAddress, amountLD: amountBigInt, minAmountLD: amountBigInt, extraOptions: params.extraOptions || "0x", composeMsg: "0x", oftCmd: "0x", }; const [nativeFee, lzFee] = await contract.quoteSend(sendParam, false); const messagingFee = { nativeFee: nativeFee, lzTokenFee: 0n, }; const tx = await contract.send( sendParam, messagingFee, await signer.getAddress(), { value: nativeFee } ); await tx.wait(); return { content: [ { type: "text", text: JSON.stringify( { transactionHash: tx.hash, fromChain: params.fromChain, toChain: params.toChain, amountSent: params.amount, sender: await signer.getAddress(), receiver: params.receiverAddress, estimatedNativeFee: formatUnits(nativeFee), }, null, 2 ), }, ], }; } catch (error: any) { console.error("Error bridging OFT:", error); return { content: [ { type: "text", text: `Error: Failed to bridge OFT: ${ error.message || error.toString() }`, }, ], isError: true, }; } }
  • Zod input schema defining parameters for the 'bridge-oft' tool: tokenAddress, amount, fromChain, toChain, receiverAddress, and optional extraOptions.
    const bridgeOftParams = z.object({ tokenAddress: z .string() .describe("The address of the OFT contract on the source chain."), amount: z.string().describe("The amount of tokens to bridge (e.g., '100')."), fromChain: networkEnum.describe("The source chain name."), toChain: networkEnum.describe("The destination chain name."), receiverAddress: z .string() .describe("The address to receive tokens on the destination chain."), extraOptions: z .string() .optional() .default("0x") .describe("Extra options for LayerZero message execution (default: '0x')."), });
  • src/index.ts:488-598 (registration)
    Registration of the 'bridge-oft' tool on the MCP server using server.tool(), specifying name, description, input schema, and handler function.
    server.tool( "bridge-oft", "Bridges OFT tokens from one chain to another using LayerZero.", bridgeOftParams.shape, async (params: z.infer<typeof bridgeOftParams>) => { try { const MyOFT = JSON.parse(await readFile(oftPath, "utf8")); const OFT_ABI = MyOFT.abi; if ( OFT_ABI === "ABI_PLACEHOLDER" || OFT_ABI === undefined || OFT_ABI.length === 0 ) { return { content: [ { type: "text", text: "Error: Placeholder ABI detected. Please replace OFT_ABI in layerzero-mcp.ts with your actual contract ABI to interact with existing contracts.", }, ], isError: true, }; } if (params.fromChain === params.toChain) { return { content: [ { type: "text", text: "Error: Source and destination chains cannot be the same.", }, ], isError: true, }; } const signer = await getSigner(params.fromChain); const fromNetworkConfig = getNetworkConfig(params.fromChain); const toNetworkConfig = getNetworkConfig(params.toChain); // Assuming 18 decimals for OFT amounts. Make this configurable if needed. const amountDecimals = 18; const amountBigInt = parseUnits(params.amount, amountDecimals); const contract = new Contract(params.tokenAddress, OFT_ABI, signer); const formattedReceiverAddress = formatAddressForLayerZero( params.receiverAddress ); const sendParam = { dstEid: toNetworkConfig.lzEid, to: formattedReceiverAddress, amountLD: amountBigInt, minAmountLD: amountBigInt, extraOptions: params.extraOptions || "0x", composeMsg: "0x", oftCmd: "0x", }; const [nativeFee, lzFee] = await contract.quoteSend(sendParam, false); const messagingFee = { nativeFee: nativeFee, lzTokenFee: 0n, }; const tx = await contract.send( sendParam, messagingFee, await signer.getAddress(), { value: nativeFee } ); await tx.wait(); return { content: [ { type: "text", text: JSON.stringify( { transactionHash: tx.hash, fromChain: params.fromChain, toChain: params.toChain, amountSent: params.amount, sender: await signer.getAddress(), receiver: params.receiverAddress, estimatedNativeFee: formatUnits(nativeFee), }, null, 2 ), }, ], }; } catch (error: any) { console.error("Error bridging OFT:", error); return { content: [ { type: "text", text: `Error: Failed to bridge OFT: ${ error.message || error.toString() }`, }, ], isError: true, }; } } );

Other Tools

Related 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/thomasfevre/layerzero_mcp'

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