Skip to main content
Glama

Algorand MCP

by GoPlausible
index.ts17.1 kB
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { env } from '../../../env.js'; export const nfdTools = [ { name: 'api_nfd_get_nfd', description: 'Get a specific NFD by name or by its application ID', inputSchema: { type: 'object', properties: { nameOrID: { type: 'string', description: 'Name of NFD or application ID' }, view: { type: 'string', enum: ['tiny', 'brief', 'full'], description: 'View of data to return' }, poll: { type: 'boolean', description: 'Use if polling waiting for state change' }, nocache: { type: 'boolean', description: 'Set to true to return a never-cached result' } }, required: ['nameOrID'] } }, { name: 'api_nfd_get_nfds_for_addresses', description: 'Get NFDs for specific addresses', inputSchema: { type: 'object', properties: { address: { type: 'array', items: { type: 'string' }, description: 'Array of addresses to look up' }, limit: { type: 'integer', description: 'Limit the number of results' }, view: { type: 'string', enum: ['tiny', 'thumbnail', 'brief', 'full'], description: 'View of data to return' } }, required: ['address'] } }, { name: 'api_nfd_get_nfd_activity', description: 'Get activity/changes for NFDs', inputSchema: { type: 'object', properties: { name: { type: 'array', items: { type: 'string' }, description: 'Array of NFD names to get activity for' }, type: { type: 'string', enum: ['changes'], description: 'Type of activity to retrieve' }, afterTime: { type: 'string', format: 'date-time', description: 'Get activity after this time' }, limit: { type: 'integer', description: 'Limit the number of results' }, sort: { type: 'string', enum: ['timeDesc', 'timeAsc'], description: 'Sort order' } }, required: ['name'] } }, { name: 'api_nfd_get_nfd_analytics', description: 'Get analytics data for NFDs', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'NFD name to filter on' }, buyer: { type: 'string', description: 'Buyer address to filter on' }, seller: { type: 'string', description: 'Seller address to filter on' }, event: { type: 'array', items: { type: 'string' }, description: 'Events to filter on' }, requireBuyer: { type: 'boolean', description: 'Whether buyer must be present' }, includeOwner: { type: 'boolean', description: 'Whether to include current owner' }, excludeNFDAsSeller: { type: 'boolean', description: 'Whether to exclude NFDomains as seller' }, category: { type: 'array', items: { type: 'string', enum: ['curated', 'premium', 'common'] } }, minPrice: { type: 'integer', description: 'Minimum price' }, maxPrice: { type: 'integer', description: 'Maximum price' }, limit: { type: 'integer', description: 'Limit the number of results' }, offset: { type: 'integer', description: 'Offset for pagination' }, sort: { type: 'string', enum: ['timeDesc', 'priceAsc', 'priceDesc'], description: 'Sort order' } } } }, { name: 'api_nfd_browse_nfds', description: 'Browse NFDs with various filters', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Name to filter on' }, category: { type: 'array', items: { type: 'string', enum: ['curated', 'premium', 'common'] } }, saleType: { type: 'array', items: { type: 'string', enum: ['auction', 'buyItNow'] } }, state: { type: 'array', items: { type: 'string', enum: ['reserved', 'forSale', 'owned', 'expired'] } }, owner: { type: 'string', description: 'Owner address to filter on' }, minPrice: { type: 'integer', description: 'Minimum price' }, maxPrice: { type: 'integer', description: 'Maximum price' }, limit: { type: 'integer', description: 'Limit the number of results' }, offset: { type: 'integer', description: 'Offset for pagination' }, sort: { type: 'string', enum: ['createdDesc', 'timeChangedDesc', 'soldDesc', 'priceAsc', 'priceDesc', 'highestSaleDesc', 'saleTypeAsc'], description: 'Sort order' }, view: { type: 'string', enum: ['tiny', 'brief', 'full'], description: 'View of data to return' } } } }, { name: 'api_nfd_search_nfds', description: 'Search NFDs with various filters', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Name to search for' }, category: { type: 'array', items: { type: 'string', enum: ['curated', 'premium', 'common'] } }, saleType: { type: 'array', items: { type: 'string', enum: ['auction', 'buyItNow'] } }, state: { type: 'array', items: { type: 'string', enum: ['reserved', 'forSale', 'owned', 'expired'] } }, owner: { type: 'string', description: 'Owner address to filter on' }, minPrice: { type: 'integer', description: 'Minimum price' }, maxPrice: { type: 'integer', description: 'Maximum price' }, limit: { type: 'integer', description: 'Limit the number of results' }, offset: { type: 'integer', description: 'Offset for pagination' }, sort: { type: 'string', enum: ['createdDesc', 'timeChangedDesc', 'soldDesc', 'priceAsc', 'priceDesc', 'highestSaleDesc', 'saleTypeAsc'], description: 'Sort order' }, view: { type: 'string', enum: ['tiny', 'brief', 'full'], description: 'View of data to return' } } } } ]; interface NFDProperties { internal?: Record<string, string>; userDefined?: Record<string, string>; verified?: Record<string, string>; } interface NFDRecord { name: string; appID?: number; asaID?: number; avatarOutdated?: boolean; caAlgo?: string[]; category?: 'curated' | 'premium' | 'common'; currentAsOfBlock?: number; depositAccount?: string; expired?: boolean; metaTags?: string[]; nfdAccount?: string; owner?: string; parentAppID?: number; properties?: NFDProperties; reservedFor?: string; saleType?: 'auction' | 'buyItNow'; sellAmount?: number; seller?: string; sigNameAddress?: string; state?: 'available' | 'minting' | 'reserved' | 'forSale' | 'owned' | 'expired'; tags?: string[]; timeChanged?: string; timeCreated?: string; timeExpires?: string; timePurchased?: string; unverifiedCa?: Record<string, string[]>; unverifiedCaAlgo?: string[]; } async function getNFD( params: { nameOrID: string; view?: 'tiny' | 'brief' | 'full'; poll?: boolean; nocache?: boolean } ): Promise<NFDRecord> { try { const searchParams = new URLSearchParams(); if (params.view) searchParams.append('view', params.view); if (params.poll) searchParams.append('poll', params.poll.toString()); if (params.nocache) searchParams.append('nocache', params.nocache.toString()); const response = await fetch(`${env.nfd_api_url}/nfd/${params.nameOrID}?${searchParams}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get NFD: ${error instanceof Error ? error.message : String(error)}` ); } } async function getNFDsForAddressesV2( params: { address: string[]; limit?: number; view?: 'tiny' | 'thumbnail' | 'brief' | 'full'; } ): Promise<Record<string, NFDRecord[]>> { try { const searchParams = new URLSearchParams(); params.address.forEach(addr => searchParams.append('address', addr)); if (params.limit) searchParams.append('limit', params.limit.toString()); if (params.view) searchParams.append('view', params.view); const response = await fetch(`${env.nfd_api_url}/nfd/v2/address?${searchParams}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get NFDs for addresses: ${error instanceof Error ? error.message : String(error)}` ); } } async function searchNFDsV2( params: { name?: string; category?: ('curated' | 'premium' | 'common')[]; saleType?: ('auction' | 'buyItNow')[]; state?: ('reserved' | 'forSale' | 'owned' | 'expired')[]; parentAppID?: number; length?: string[]; traits?: ('emoji' | 'pristine' | 'segment')[]; owner?: string; reservedFor?: string; prefix?: string; substring?: string; vproperty?: string; vvalue?: string; minPrice?: number; maxPrice?: number; changedAfter?: string; limit?: number; offset?: number; sort?: string; view?: 'tiny' | 'brief' | 'full'; } ): Promise<{ total: number; nfds: NFDRecord[] }> { try { const searchParams = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined) { if (Array.isArray(value)) { value.forEach(v => searchParams.append(key, v.toString())); } else { searchParams.append(key, value.toString()); } } }); const response = await fetch(`${env.nfd_api_url}/nfd/v2/search?${searchParams}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to search NFDs: ${error instanceof Error ? error.message : String(error)}` ); } } async function browseNFDs( params: { name?: string; category?: ('curated' | 'premium' | 'common')[]; saleType?: ('auction' | 'buyItNow')[]; state?: ('reserved' | 'forSale' | 'owned' | 'expired')[]; parentAppID?: number; length?: string[]; traits?: ('emoji' | 'pristine' | 'segment')[]; owner?: string; reservedFor?: string; prefix?: string; substring?: string; vproperty?: string; vvalue?: string; minPrice?: number; maxPrice?: number; changedAfter?: string; limit?: number; offset?: number; sort?: string; view?: 'tiny' | 'brief' | 'full'; } ): Promise<NFDRecord[]> { try { const searchParams = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined) { if (Array.isArray(value)) { value.forEach(v => searchParams.append(key, v.toString())); } else { searchParams.append(key, value.toString()); } } }); const response = await fetch(`${env.nfd_api_url}/nfd/browse?${searchParams}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to browse NFDs: ${error instanceof Error ? error.message : String(error)}` ); } } async function getNFDActivity( params: { name: string[]; type?: 'changes'; afterTime?: string; limit?: number; sort?: 'timeDesc' | 'timeAsc'; } ): Promise<{ block: number; changes: Record<string, string>; name: string; timeChanged: string; }[]> { try { const searchParams = new URLSearchParams(); params.name.forEach(n => searchParams.append('name', n)); if (params.type) searchParams.append('type', params.type); if (params.afterTime) searchParams.append('afterTime', params.afterTime); if (params.limit) searchParams.append('limit', params.limit.toString()); if (params.sort) searchParams.append('sort', params.sort); const response = await fetch(`${env.nfd_api_url}/nfd/activity?${searchParams}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get NFD activity: ${error instanceof Error ? error.message : String(error)}` ); } } async function getNFDAnalytics( params: { name?: string; buyer?: string; seller?: string; event?: string[]; requireBuyer?: boolean; includeOwner?: boolean; excludeNFDAsSeller?: boolean; category?: string[]; saleType?: string[]; length?: string[]; traits?: string[]; parentAppID?: number; minPrice?: number; maxPrice?: number; afterTime?: string; limit?: number; offset?: number; sort?: 'timeDesc' | 'priceAsc' | 'priceDesc'; } ): Promise<{ total: number; results: { data: { block: number; buyer?: string; carryCost?: number; category?: string; currentOwner?: string; event: string; groupID?: string; metaTags?: string[]; name: string; newExpTime?: string; note?: string; oneYearRenewalPrice?: number; saleType?: string; seller?: string; }; price: number; priceUsd?: number; timestamp: string; }[]; }> { try { const searchParams = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined) { if (Array.isArray(value)) { value.forEach(v => searchParams.append(key, v.toString())); } else { searchParams.append(key, value.toString()); } } }); const response = await fetch(`${env.nfd_api_url}/nfd/analytics?${searchParams}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get NFD analytics: ${error instanceof Error ? error.message : String(error)}` ); } } export async function handleNFDTools(name: string, args: any): Promise<any> { try { let result; switch (name) { case 'api_nfd_get_nfd': { result = await getNFD(args); break; } case 'api_nfd_get_nfds_for_addresses': { result = await getNFDsForAddressesV2(args); break; } case 'api_nfd_get_nfd_activity': { result = await getNFDActivity(args); break; } case 'api_nfd_get_nfd_analytics': { result = await getNFDAnalytics(args); break; } case 'api_nfd_browse_nfds': { result = await browseNFDs(args); break; } case 'api_nfd_search_nfds': { result = await searchNFDsV2(args); break; } default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${name}` ); } return result } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to handle NFD tool: ${error instanceof Error ? error.message : String(error)}` ); } }

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/GoPlausible/algorand-mcp'

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