Skip to main content
Glama

get_nft_info

Retrieve ERC721 NFT details including metadata URI by providing contract address and token ID on EVM-compatible networks.

Instructions

Get information about an ERC721 NFT including metadata URI

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contractAddressYesThe NFT contract address
tokenIdYesThe NFT token ID
networkNoNetwork name or chain ID. Defaults to Ethereum mainnet.

Implementation Reference

  • Registration of the 'get_nft_info' tool on the MCP server, including input schema and inline handler function.
    'get_nft_info', 'Get detailed information about a specific NFT (ERC721 token), including collection name, symbol, token URI, and current owner if available.', { 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 token to query (e.g., '1234')"), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Most NFTs are on Ethereum mainnet, which is the default." ) }, async ({ tokenAddress, tokenId, network = 'ethereum' }) => { try { const nftInfo = await services.getERC721TokenMetadata( tokenAddress as Address, BigInt(tokenId), network ); // Check ownership separately let owner = null; try { // This may fail if tokenId doesn't exist owner = await services.getPublicClient(network).readContract({ address: tokenAddress as Address, abi: [ { inputs: [{ type: 'uint256' }], name: 'ownerOf', outputs: [{ type: 'address' }], stateMutability: 'view', type: 'function' } ], functionName: 'ownerOf', args: [BigInt(tokenId)] }); } catch (e) { // Ownership info not available } return { content: [ { type: 'text', text: JSON.stringify( { contract: tokenAddress, tokenId, network, ...nftInfo, owner: owner || 'Unknown' }, null, 2 ) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error fetching NFT info: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } }
  • Handler function that executes the tool logic, calling getERC721TokenMetadata and ownerOf to fetch NFT details.
    'get_nft_info', 'Get detailed information about a specific NFT (ERC721 token), including collection name, symbol, token URI, and current owner if available.', { 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 token to query (e.g., '1234')"), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Most NFTs are on Ethereum mainnet, which is the default." ) }, async ({ tokenAddress, tokenId, network = 'ethereum' }) => { try { const nftInfo = await services.getERC721TokenMetadata( tokenAddress as Address, BigInt(tokenId), network ); // Check ownership separately let owner = null; try { // This may fail if tokenId doesn't exist owner = await services.getPublicClient(network).readContract({ address: tokenAddress as Address, abi: [ { inputs: [{ type: 'uint256' }], name: 'ownerOf', outputs: [{ type: 'address' }], stateMutability: 'view', type: 'function' } ], functionName: 'ownerOf', args: [BigInt(tokenId)] }); } catch (e) { // Ownership info not available } return { content: [ { type: 'text', text: JSON.stringify( { contract: tokenAddress, tokenId, network, ...nftInfo, owner: owner || 'Unknown' }, null, 2 ) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error fetching NFT info: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } }
  • Zod input schema for validating tool parameters: tokenAddress, tokenId, network.
    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 token to query (e.g., '1234')"), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', 'polygon') or chain ID. Most NFTs are on Ethereum mainnet, which is the default." ) },
  • Core helper function that reads name, symbol, and tokenURI from ERC721 contract using viem's getContract.
    export async function getERC721TokenMetadata( tokenAddress: Address, tokenId: bigint, network: string = 'ethereum' ): Promise<{ name: string; symbol: string; tokenURI: string; }> { const publicClient = getPublicClient(network); const contract = getContract({ address: tokenAddress, abi: erc721Abi, client: publicClient, }); const [name, symbol, tokenURI] = await Promise.all([ contract.read.name(), contract.read.symbol(), contract.read.tokenURI([tokenId]) ]); return { name, symbol, tokenURI }; }
  • ERC721 ABI used for reading NFT metadata (name, symbol, tokenURI).
    const erc721Abi = [ { inputs: [], name: 'name', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'symbol', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' }, { inputs: [{ type: 'uint256', name: 'tokenId' }], name: 'tokenURI', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' }

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/chulanpro5/evm-mcp-server'

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