transfer_nft
Transfer an NFT between wallets on the BNB Chain by providing the private key, token address, token ID, and recipient address. Securely sign and execute transactions.
Instructions
Transfer an NFT (ERC721 token) from one address to another. Requires the private key of the current owner for signing the transaction.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| network | No | Network name (e.g. 'bsc', 'opbnb', 'ethereum', 'base', etc.) or chain ID. Supports others main popular networks. Defaults to BSC mainnet. | bsc |
| privateKey | No | Private key of the NFT owner account in hex format (with or without 0x prefix). SECURITY: This is used only for transaction signing and is not stored. | 0x5a2b7e4d9c8f1a3e6b0d2c5f4e3d2a1b0c9f8e7d6a5b4c3d2e1f0a9b8c7d6e5f4 |
| toAddress | Yes | The recipient wallet address that will receive the NFT | |
| tokenAddress | Yes | The contract address of the NFT collection (e.g., '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' for Bored Ape Yacht Club) | |
| tokenId | Yes | The ID of the specific NFT to transfer (e.g., '1234') |
Implementation Reference
- src/evm/modules/nft/tools.ts:73-120 (registration)MCP tool registration for 'transfer_nft', including input schema (zod), description, and inline handler function that invokes the transferERC721 service and formats the response.server.tool( "transfer_nft", "Transfer an NFT to an address", { privateKey: z .string() .describe( "Private key of the owner's account in hex format (with or without 0x prefix). SECURITY: This is used only for transaction signing and is not stored." ) .default(process.env.PRIVATE_KEY as string), tokenAddress: z .string() .describe( "The contract address of the NFT collection (e.g., '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' for Bored Ape Yacht Club)" ), tokenId: z .string() .describe("The ID of the specific NFT to transfer (e.g., '1234')"), toAddress: z .string() .describe("The recipient address that will receive the NFT"), network: defaultNetworkParam }, async ({ privateKey, tokenAddress, tokenId, toAddress, network }) => { try { const result = await services.transferERC721( tokenAddress as Address, toAddress as Address, BigInt(tokenId), privateKey, network ) return mcpToolRes.success({ success: true, txHash: result.txHash, network, contract: tokenAddress, tokenId: result.tokenId, recipient: toAddress, name: result.token.name, symbol: result.token.symbol }) } catch (error) { return mcpToolRes.error(error, "transferring NFT") } } )
- src/evm/modules/nft/tools.ts:96-119 (handler)The handler function for the transfer_nft MCP tool, which calls the underlying transferERC721 service, handles errors, and returns formatted success/error response.async ({ privateKey, tokenAddress, tokenId, toAddress, network }) => { try { const result = await services.transferERC721( tokenAddress as Address, toAddress as Address, BigInt(tokenId), privateKey, network ) return mcpToolRes.success({ success: true, txHash: result.txHash, network, contract: tokenAddress, tokenId: result.tokenId, recipient: toAddress, name: result.token.name, symbol: result.token.symbol }) } catch (error) { return mcpToolRes.error(error, "transferring NFT") } }
- src/evm/services/transfer.ts:222-282 (helper)Supporting utility function transferERC721 that executes the actual ERC721 NFT transfer using transferFrom, handles ENS resolution, fetches token metadata, and returns transaction details.export async function transferERC721( tokenAddressOrEns: string, toAddressOrEns: string, tokenId: bigint, privateKey: string | `0x${string}`, network: string = "ethereum" ): Promise<{ txHash: Hash tokenId: string token: { name: string symbol: string } }> { // Resolve ENS names to addresses if needed const tokenAddress = (await resolveAddress( tokenAddressOrEns, network )) as Address const toAddress = (await resolveAddress(toAddressOrEns, network)) as Address // Ensure the private key has 0x prefix const formattedKey = typeof privateKey === "string" && !privateKey.startsWith("0x") ? (`0x${privateKey}` as `0x${string}`) : (privateKey as `0x${string}`) // Get token details const publicClient = getPublicClient(network) const contract = getContract({ address: tokenAddress, abi: ERC721_ABI, client: publicClient }) // Get token name and symbol const name = (await contract.read.name()) as string const symbol = (await contract.read.symbol()) as string // Create wallet client for sending the transaction const walletClient = getWalletClient(formattedKey, network) // Send the transaction const hash = await walletClient.writeContract({ address: tokenAddress, abi: ERC721_ABI, functionName: "transferFrom", args: [walletClient.account!.address, toAddress, tokenId], account: walletClient.account!, chain: walletClient.chain }) return { txHash: hash, tokenId: tokenId.toString(), token: { name, symbol } } }