crypto_monthly
Fetch monthly time series data for any cryptocurrency by specifying its symbol and market. Supports JSON and CSV formats for easy integration and analysis.
Instructions
Fetches monthly time series data for a cryptocurrency.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| datatype | No | Data format for the response. | json |
| market | Yes | The exchange market (e.g., "USD", "EUR"). | |
| symbol | Yes | The cryptocurrency symbol (e.g., "BTC"). |
Implementation Reference
- src/index.ts:537-548 (registration)Registers the MCP tool 'crypto_monthly' with description, parameters schema, and execute handler that delegates to executeAvantageTool calling av.crypto.monthlyserver.addTool({ name: "crypto_monthly", description: "Fetches monthly time series data for a cryptocurrency.", parameters: schemas.CryptoTimeSeriesParamsSchema, execute: ( args, context // Let type be inferred ) => executeAvantageTool("crypto_monthly", args, context, (av, params) => av.crypto.monthly(params) ), });
- src/schemas.ts:112-116 (schema)Defines the Zod input schema CryptoTimeSeriesParamsSchema used by crypto_monthly (and other crypto time series tools) requiring symbol, market, and optional datatypeexport const CryptoTimeSeriesParamsSchema = z.object({ symbol: z.string().describe('The cryptocurrency symbol (e.g., "BTC").'), market: z.string().describe('The exchange market (e.g., "USD", "EUR").'), datatype: DatatypeSchema.default('json').optional(), }).describe('Parameters for fetching daily/weekly/monthly crypto time series data.')
- src/index.ts:38-115 (handler)Generic handler executeAvantageTool invoked by crypto_monthly (and all similar tools) managing authentication, resource pooling, AVantage library invocation (av.crypto.monthly), and response formattingasync function executeAvantageTool<TArgs, TResult>( toolName: string, args: TArgs, context: Context<Record<string, unknown> | undefined>, // Use the imported Context type directly avantageMethod: ( av: AVantage, args: TArgs ) => Promise<{ error?: boolean; reason?: string; data?: TResult }> ): Promise<string> { logger.info(`Executing '${toolName}' tool for request ID: ${context}`); logger.debug(`Args for ${toolName}: ${JSON.stringify(args)}`); // --- Authentication & Resource Management --- // Access extraArgs safely - it might be null or undefined const extraArgsApiKey = context.extraArgs?.apiKey as string | undefined; const apiKey = extraArgsApiKey || config.apiKey; if (!apiKey) { logger.error(`'${toolName}' failed: Alpha Vantage API key missing.`); throw new UserError(apiKeyErrorMessage); } logger.debug( `Using AV API key (source: ${extraArgsApiKey ? "extraArgs" : "environment"}) for ${toolName}` ); try { // Get or create AVantage instance managed by ResourceManager const av = await resourceManager.getResource<AVantage>( apiKey, // Cache key is the resolved API key "avantage_client", // Type identifier for logging async (key) => { // Factory Function logger.info( `Creating new AVantage instance for key ending ...${key.slice(-4)}` ); // AVantage library reads AV_PREMIUM from process.env internally return new AVantage(key); }, async (avInstance) => { // Cleanup Function (no-op needed for AVantage) logger.debug(`Destroying AVantage instance (no-op)`); } ); // --- Library Call --- const result = await avantageMethod(av, args); // --- Response Handling --- if (result.error) { logger.warn( `'${toolName}' failed. Reason from avantage: ${result.reason}` ); throw new UserError(result.reason || `Tool '${toolName}' failed.`); } if (result.data === undefined || result.data === null) { logger.warn(`'${toolName}' completed successfully but returned no data.`); return "null"; // Return string "null" for empty data } logger.info(`'${toolName}' completed successfully.`); // Stringify the data part of the response return JSON.stringify(result.data); } catch (error: any) { logger.error( `Error during execution of '${toolName}': ${error.message}`, error ); // If it's already a UserError, rethrow it if (error instanceof UserError) { throw error; } // Otherwise, wrap it in a UserError throw new UserError( `An unexpected error occurred while executing tool '${toolName}': ${error.message}` ); } }