Skip to main content
Glama
index.ts3.38 kB
import { ActionProvider, CreateAction, EvmWalletProvider, type Network, } from '@coinbase/agentkit'; import { isAddress } from 'viem'; import { base } from 'viem/chains'; import type { z } from 'zod'; import { chainIdToChain } from '../../chains.js'; import { constructBaseScanUrl } from '../utils/index.js'; import { ListNftsSchema, TransferNftSchema } from './schemas.js'; import { detectStandardAndTransferNft, fetchNftsFromAlchemy, formatNftData, } from './utils.js'; export class BaseMcpNftActionProvider extends ActionProvider<EvmWalletProvider> { constructor() { super('baseMcpNft', []); } @CreateAction({ name: 'list_nfts', description: 'List NFTs owned by a specific address', schema: ListNftsSchema, }) async listNfts( walletProvider: EvmWalletProvider, args: z.infer<typeof ListNftsSchema>, ) { try { // Validate owner address if (!isAddress(args.ownerAddress)) { throw new Error(`Invalid owner address: ${args.ownerAddress}`); } // Fetch NFTs from Alchemy API const nftData = await fetchNftsFromAlchemy({ ownerAddress: args.ownerAddress, limit: args.limit, }); // Format the NFT data const nfts = formatNftData({ nftData, }); // Format the result if (nfts.length === 0) { return 'No NFTs found for this address.'; } const formattedNfts = nfts .map((nft, index) => { return `${index + 1}. ${nft.title} (${nft.tokenType}) Contract: ${nft.contractAddress} Token ID: ${nft.tokenId} ${nft.imageUrl ? `Image: ${nft.imageUrl}` : ''}`; }) .join('\n\n'); return `Found ${nfts.length} NFTs:\n\n${formattedNfts}`; } catch (error) { console.error('Error listing NFTs:', error); return `Error listing NFTs: ${error instanceof Error ? error.message : String(error)}`; } } @CreateAction({ name: 'transfer_nft', description: 'Transfer an NFT to another address', schema: TransferNftSchema, }) async transferNft( walletProvider: EvmWalletProvider, args: z.infer<typeof TransferNftSchema>, ) { try { // Validate addresses if (!isAddress(args.contractAddress)) { throw new Error(`Invalid contract address: ${args.contractAddress}`); } if (!isAddress(args.toAddress)) { throw new Error(`Invalid recipient address: ${args.toAddress}`); } // // Execute the transfer const txHash = await detectStandardAndTransferNft({ wallet: walletProvider, contractAddress: args.contractAddress, tokenId: args.tokenId, toAddress: args.toAddress, amount: args.amount, }); const chain = chainIdToChain(walletProvider.getNetwork().chainId ?? base.id) ?? base; const txUrl = constructBaseScanUrl(chain, txHash); return `NFT transfer initiated!\n\nTransaction: ${txUrl}\n\nPlease wait for the transaction to be confirmed.`; } catch (error) { console.error('Error transferring NFT:', error); return `Error transferring NFT: ${error instanceof Error ? error.message : String(error)}`; } } supportsNetwork(network: Network): boolean { return network.chainId === String(base.id); } } export const baseMcpNftActionProvider = () => new BaseMcpNftActionProvider();

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/bioanywhere/mcp-base-mcp2'

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