check_nft_ownership
Verify NFT ownership by checking if a specific wallet address holds a particular NFT within an EVM-compatible blockchain network, using contract address, token ID, and owner details.
Instructions
Check if an address owns a specific NFT
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| network | No | Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet. | |
| ownerAddress | Yes | The wallet address or ENS name to check ownership against (e.g., '0x1234...' or 'vitalik.eth') | |
| tokenAddress | Yes | The contract address or ENS name of the NFT collection (e.g., '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' for BAYC or 'boredapeyachtclub.eth') | |
| tokenId | Yes | The ID of the NFT to check (e.g., '1234') |
Implementation Reference
- src/core/tools.ts:1482-1546 (handler)The primary handler function for the 'check_nft_ownership' MCP tool. It validates inputs using Zod schemas, calls the isNFTOwner service helper, formats the response as JSON text content, and handles errors.server.tool( 'check_nft_ownership', 'Check if an address owns a specific NFT', { tokenAddress: z .string() .describe( "The contract address or ENS name of the NFT collection (e.g., '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' for BAYC or 'boredapeyachtclub.eth')" ), tokenId: z.string().describe("The ID of the NFT to check (e.g., '1234')"), ownerAddress: z .string() .describe( "The wallet address or ENS name to check ownership against (e.g., '0x1234...' or 'vitalik.eth')" ), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet." ) }, async ({ tokenAddress, tokenId, ownerAddress, network = 'ethereum' }) => { try { const isOwner = await services.isNFTOwner( tokenAddress, ownerAddress, BigInt(tokenId), network ); return { content: [ { type: 'text', text: JSON.stringify( { tokenAddress, tokenId, ownerAddress, network, isOwner, result: isOwner ? 'Address owns this NFT' : 'Address does not own this NFT' }, null, 2 ) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error checking NFT ownership: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } );
- src/core/tools.ts:1486-1503 (schema)Zod input schema defining parameters for the check_nft_ownership tool: tokenAddress, tokenId, ownerAddress, and optional network.tokenAddress: z .string() .describe( "The contract address or ENS name of the NFT collection (e.g., '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' for BAYC or 'boredapeyachtclub.eth')" ), tokenId: z.string().describe("The ID of the NFT to check (e.g., '1234')"), ownerAddress: z .string() .describe( "The wallet address or ENS name to check ownership against (e.g., '0x1234...' or 'vitalik.eth')" ), network: z .string() .optional() .describe( "Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet." ) },
- src/core/tools.ts:1482-1483 (registration)Registration of the 'check_nft_ownership' tool with the MCP server via server.tool().server.tool( 'check_nft_ownership',
- src/core/services/balance.ts:146-169 (helper)Core helper function that implements NFT ownership check by calling ownerOf on ERC721 contract via readContract, after resolving ENS names if necessary.export async function isNFTOwner( tokenAddressOrEns: string, ownerAddressOrEns: string, tokenId: bigint, network = 'ethereum' ): Promise<boolean> { // Resolve ENS names to addresses if needed const tokenAddress = await resolveAddress(tokenAddressOrEns, network); const ownerAddress = await resolveAddress(ownerAddressOrEns, network); try { const actualOwner = await readContract({ address: tokenAddress, abi: erc721Abi, functionName: 'ownerOf', args: [tokenId] }, network) as Address; return actualOwner.toLowerCase() === ownerAddress.toLowerCase(); } catch (error: any) { console.error(`Error checking NFT ownership: ${error.message}`); return false; } }
- src/core/services/balance.ts:38-52 (helper)ERC721 ABI fragment used by isNFTOwner for calling ownerOf function.const erc721Abi = [ { inputs: [{ type: 'address', name: 'owner' }], name: 'balanceOf', outputs: [{ type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [{ type: 'uint256', name: 'tokenId' }], name: 'ownerOf', outputs: [{ type: 'address' }], stateMutability: 'view', type: 'function' }