fetchTokenPriceHistoryByTimeFrame
Retrieve historical cryptocurrency price data for specific tokens over defined time periods. Query price trends by specifying token symbol, timeframe, and interval to analyze market movements.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | The token symbol to query. e.g. "BTC" or "ETH" | |
| timeFrame | Yes | Time frame like "last-week", "past-7d", "ytd", "last-month", etc. or use natural language like "last week" | |
| interval | No | The interval to query. e.g. "1d" or "1h" | 1d |
| useNaturalLanguageProcessing | No | If true, will interpret timeFrame as natural language |
Implementation Reference
- index.ts:99-139 (registration)MCP tool registration including Zod input schema and the handler function. The handler processes the timeFrame parameter (supporting natural language via flag), computes date range using helpers, calls alchemyApi for price history, and formats response as text or error.server.tool('fetchTokenPriceHistoryByTimeFrame', { symbol: z.string().describe('The token symbol to query. e.g. "BTC" or "ETH"'), timeFrame: z.string().describe('Time frame like "last-week", "past-7d", "ytd", "last-month", etc. or use natural language like "last week"'), interval: z.string().default('1d').describe('The interval to query. e.g. "1d" or "1h"'), useNaturalLanguageProcessing: z.boolean().default(false).describe('If true, will interpret timeFrame as natural language'), }, async (params) => { try { // Process time frame - either directly or through NLP let timeFrame = params.timeFrame; if (params.useNaturalLanguageProcessing) { timeFrame = parseNaturalLanguageTimeFrame(params.timeFrame); } // Calculate date range const { startDate, endDate } = calculateDateRange(timeFrame); // Fetch the data const result = await alchemyApi.getTokenPriceHistoryBySymbol({ symbol: params.symbol, startTime: startDate, endTime: endDate, interval: params.interval }); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } catch (error) { if (error instanceof Error) { console.error('Error in fetchTokenPriceHistoryByTimeFrame:', error); return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true }; } return { content: [{ type: "text", text: 'Unknown error occurred' }], isError: true }; } });
- utils/dateUtils.ts:8-97 (helper)Utility function to calculate startDate and endDate ISO strings from various time frame formats (e.g., 'past-7d', 'ytd', 'last-month') used in the tool handler.export function calculateDateRange(timeFrame: string): DateRange { // If timeFrame is a simple keyword that toISO8601 can handle directly if (['today', 'yesterday', 'last-week', 'last-month', 'start-of-year'].includes(timeFrame.toLowerCase())) { return { startDate: toISO8601(timeFrame), endDate: toISO8601('now') }; } const now = new Date(); let startDate = new Date(now); let endDate = new Date(now); const normalizedTimeFrame = timeFrame.toLowerCase(); // Handle special cases first if (normalizedTimeFrame === 'previous-calendar-week') { const today = now.getDay(); // 0 is Sunday, 6 is Saturday // Calculate previous week's Sunday startDate = new Date(now); startDate.setDate(now.getDate() - today - 7); startDate.setHours(0, 0, 0, 0); // Calculate previous week's Saturday endDate = new Date(startDate); endDate.setDate(startDate.getDate() + 6); endDate.setHours(23, 59, 59, 999); } // Handle trailing periods (last 7 days, etc.) else if (normalizedTimeFrame === 'last-7-days' || normalizedTimeFrame === 'last-week') { startDate.setDate(now.getDate() - 7); } // Handle past-Nd format (days) else if (normalizedTimeFrame.startsWith('past-') && normalizedTimeFrame.endsWith('d')) { const days = parseInt(normalizedTimeFrame.substring(5, normalizedTimeFrame.length - 1)); if (!isNaN(days)) { startDate.setDate(now.getDate() - days); } } // Handle past-Nw format (weeks) else if (normalizedTimeFrame.startsWith('past-') && normalizedTimeFrame.endsWith('w')) { const weeks = parseInt(normalizedTimeFrame.substring(5, normalizedTimeFrame.length - 1)); if (!isNaN(weeks)) { startDate.setDate(now.getDate() - (weeks * 7)); } } // Handle past-Nm format (months) else if (normalizedTimeFrame.startsWith('past-') && normalizedTimeFrame.endsWith('m')) { const months = parseInt(normalizedTimeFrame.substring(5, normalizedTimeFrame.length - 1)); if (!isNaN(months)) { startDate.setMonth(now.getMonth() - months); } } // Handle past-Ny format (years) else if (normalizedTimeFrame.startsWith('past-') && normalizedTimeFrame.endsWith('y')) { const years = parseInt(normalizedTimeFrame.substring(5, normalizedTimeFrame.length - 1)); if (!isNaN(years)) { startDate.setFullYear(now.getFullYear() - years); } } // Handle ytd (year to date) else if (normalizedTimeFrame === 'ytd') { startDate = new Date(now.getFullYear(), 0, 1); // January 1st of current year } // Handle qtd (quarter to date) else if (normalizedTimeFrame === 'qtd') { const quarter = Math.floor(now.getMonth() / 3); startDate = new Date(now.getFullYear(), quarter * 3, 1); } // Handle mtd (month to date) else if (normalizedTimeFrame === 'mtd') { startDate = new Date(now.getFullYear(), now.getMonth(), 1); } // Handle wtd (week to date - starting from Sunday) else if (normalizedTimeFrame === 'wtd') { const day = now.getDay(); // 0 = Sunday, 6 = Saturday startDate.setDate(now.getDate() - day); } // Default to 7 days if format not recognized else { startDate.setDate(now.getDate() - 7); console.warn(`Unrecognized timeFrame format: ${timeFrame}. Defaulting to past 7 days.`); } return { startDate: startDate.toISOString(), endDate: endDate.toISOString() }; }
- utils/dateUtils.ts:105-135 (helper)Utility function to convert natural language time descriptions (e.g., 'last week') to standardized time frame strings for use in date range calculation.export function parseNaturalLanguageTimeFrame(query: string): string { const normalizedQuery = query.toLowerCase(); if (normalizedQuery.includes('last week') || normalizedQuery.includes('previous week')) { return 'last-week'; } else if (normalizedQuery.includes('last month') || normalizedQuery.includes('previous month')) { return 'last-month'; } else if (normalizedQuery.includes('yesterday')) { return 'yesterday'; } else if (normalizedQuery.includes('last year') || normalizedQuery.includes('previous year')) { return 'past-1y'; } else if (normalizedQuery.includes('this year') || normalizedQuery.includes('year to date') || normalizedQuery.includes('ytd')) { return 'ytd'; } else if (normalizedQuery.includes('this month') || normalizedQuery.includes('month to date') || normalizedQuery.includes('mtd')) { return 'mtd'; } else if (normalizedQuery.includes('this quarter') || normalizedQuery.includes('quarter to date') || normalizedQuery.includes('qtd')) { return 'qtd'; } else if (normalizedQuery.includes('calendar week')) { return 'previous-calendar-week'; } // Default to last 7 days if no specific time frame mentioned return 'last-7-days'; }
- api/alchemyApi.ts:48-63 (helper)API helper called by the tool handler to fetch historical token prices from Alchemy's Prices API using symbol, startTime, endTime, and interval.async getTokenPriceHistoryBySymbol(params: TokenPriceHistoryBySymbol) { console.log('Fetching token price history for symbol:', params.symbol); try { const client = createPricesClient(); const response = await client.post('/historical', { ...params }); console.log('Successfully fetched token price history:', response.data); return response.data; } catch (error) { console.error('Error fetching token price history:', error); throw error; } },
- types/types.d.ts:15-25 (schema)TypeScript interface defining parameters for getTokenPriceHistoryBySymbol, used by the alchemyApi helper.export interface TokenPriceHistoryBySymbol { symbol: string; startTime: string; endTime: string; interval: string; } // || ** MultiChain Token API ** || export interface MultiChainTokenByAddress { addresses: AddressPair[]; }