getAINews
Search AI-related crypto and Web3 news by filtering with categories, blockchains, tokens, keywords, and date range.
Instructions
Fetch the latest AI-related crypto and Web3 news with optional filtering by categories, blockchains, tokens, keywords, and date range
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| categories | No | Categories to filter by (e.g., ['defi', 'nft', 'gaming', 'dao', 'metaverse']) | |
| blockchains | No | Blockchains/networks to filter by (e.g., ['ethereum', 'bitcoin', 'solana', 'polygon']) | |
| tokens | No | Tokens/cryptocurrencies to filter by (e.g., ['bitcoin', 'ethereum', 'usdt', 'bnb']) | |
| searchQuery | No | Keyword or phrase to search for in news titles and descriptions | |
| fetchAfter | No | Only return news published after this date (ISO 8601 format, e.g., '2024-01-01T00:00:00Z') | |
| limit | No | Number of news articles to return (default: 10) | |
| offset | No | Number of items to skip for pagination (default: 0) |
Implementation Reference
- index.js:197-316 (registration)The tool is registered with the MCP server using server.tool(), defining its name, description, schema, and handler.
server.tool( "getAINews", "Fetch the latest AI-related crypto and Web3 news with optional filtering by categories, blockchains, tokens, keywords, and date range", { categories: z.array(z.string()).optional().describe("Categories to filter by (e.g., ['defi', 'nft', 'gaming', 'dao', 'metaverse'])"), blockchains: z.array(z.string()).optional().describe("Blockchains/networks to filter by (e.g., ['ethereum', 'bitcoin', 'solana', 'polygon'])"), tokens: z.array(z.string()).optional().describe("Tokens/cryptocurrencies to filter by (e.g., ['bitcoin', 'ethereum', 'usdt', 'bnb'])"), searchQuery: z.string().optional().describe("Keyword or phrase to search for in news titles and descriptions"), fetchAfter: z.string().optional().describe("Only return news published after this date (ISO 8601 format, e.g., '2024-01-01T00:00:00Z')"), limit: z.number().default(10).describe("Number of news articles to return (default: 10)"), offset: z.number().default(0).describe("Number of items to skip for pagination (default: 0)") }, async ({ categories, blockchains, tokens, searchQuery, fetchAfter, limit = 10, offset = 0 }) => { try { const apiKey = process.env.CHAINGPT_API_KEY; if (!apiKey) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: "ChainGPT API key not found. Please set the CHAINGPT_API_KEY environment variable.", suggestion: "Add CHAINGPT_API_KEY=your_api_key to your environment variables" }, null, 2) }] }; } const client = initializeClient(apiKey); const categoryIds = parseTermsToIds(categories, CATEGORY_MAPPINGS); const subCategoryIds = parseTermsToIds(blockchains, SUBCATEGORY_MAPPINGS); const tokenIds = parseTermsToIds(tokens, TOKEN_MAPPINGS); const requestParams = { limit, offset, sortBy: 'createdAt' }; if (categoryIds.length > 0) { requestParams.categoryId = categoryIds; } if (subCategoryIds.length > 0) { requestParams.subCategoryId = subCategoryIds; } if (tokenIds.length > 0) { requestParams.tokenId = tokenIds; } if (searchQuery) { requestParams.searchQuery = searchQuery; } if (fetchAfter) { try { requestParams.fetchAfter = new Date(fetchAfter); } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: "Invalid date format for fetchAfter. Please use ISO 8601 format (e.g., '2024-01-01T00:00:00Z')", providedDate: fetchAfter }, null, 2) }] }; } } const response = await client.getNews(requestParams); const result = { status: "success", metadata: { totalResults: response.data.length, limit, offset, appliedFilters: { categories: categories || [], blockchains: blockchains || [], tokens: tokens || [], searchQuery: searchQuery || null, fetchAfter: fetchAfter || null, mappedIds: { categoryIds, subCategoryIds, tokenIds } }, timestamp: new Date().toISOString() }, data: response.data }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: `Failed to fetch AI news: ${error.message}`, errorType: error.constructor.name, timestamp: new Date().toISOString() }, null, 2) }] }; } } ); - index.js:200-208 (schema)Zod schema defining the input parameters for the getAINews tool.
{ categories: z.array(z.string()).optional().describe("Categories to filter by (e.g., ['defi', 'nft', 'gaming', 'dao', 'metaverse'])"), blockchains: z.array(z.string()).optional().describe("Blockchains/networks to filter by (e.g., ['ethereum', 'bitcoin', 'solana', 'polygon'])"), tokens: z.array(z.string()).optional().describe("Tokens/cryptocurrencies to filter by (e.g., ['bitcoin', 'ethereum', 'usdt', 'bnb'])"), searchQuery: z.string().optional().describe("Keyword or phrase to search for in news titles and descriptions"), fetchAfter: z.string().optional().describe("Only return news published after this date (ISO 8601 format, e.g., '2024-01-01T00:00:00Z')"), limit: z.number().default(10).describe("Number of news articles to return (default: 10)"), offset: z.number().default(0).describe("Number of items to skip for pagination (default: 0)") }, - index.js:209-315 (handler)The handler function that executes the tool logic: validates API key, maps terms to IDs, calls the ChainGPT AI News API, and returns formatted results.
async ({ categories, blockchains, tokens, searchQuery, fetchAfter, limit = 10, offset = 0 }) => { try { const apiKey = process.env.CHAINGPT_API_KEY; if (!apiKey) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: "ChainGPT API key not found. Please set the CHAINGPT_API_KEY environment variable.", suggestion: "Add CHAINGPT_API_KEY=your_api_key to your environment variables" }, null, 2) }] }; } const client = initializeClient(apiKey); const categoryIds = parseTermsToIds(categories, CATEGORY_MAPPINGS); const subCategoryIds = parseTermsToIds(blockchains, SUBCATEGORY_MAPPINGS); const tokenIds = parseTermsToIds(tokens, TOKEN_MAPPINGS); const requestParams = { limit, offset, sortBy: 'createdAt' }; if (categoryIds.length > 0) { requestParams.categoryId = categoryIds; } if (subCategoryIds.length > 0) { requestParams.subCategoryId = subCategoryIds; } if (tokenIds.length > 0) { requestParams.tokenId = tokenIds; } if (searchQuery) { requestParams.searchQuery = searchQuery; } if (fetchAfter) { try { requestParams.fetchAfter = new Date(fetchAfter); } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: "Invalid date format for fetchAfter. Please use ISO 8601 format (e.g., '2024-01-01T00:00:00Z')", providedDate: fetchAfter }, null, 2) }] }; } } const response = await client.getNews(requestParams); const result = { status: "success", metadata: { totalResults: response.data.length, limit, offset, appliedFilters: { categories: categories || [], blockchains: blockchains || [], tokens: tokens || [], searchQuery: searchQuery || null, fetchAfter: fetchAfter || null, mappedIds: { categoryIds, subCategoryIds, tokenIds } }, timestamp: new Date().toISOString() }, data: response.data }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: `Failed to fetch AI news: ${error.message}`, errorType: error.constructor.name, timestamp: new Date().toISOString() }, null, 2) }] }; } } - index.js:167-179 (helper)Helper function to convert human-readable category/blockchain/token names to their numeric IDs using the mapping objects.
function parseTermsToIds(terms, mappingObject) { if (!terms || !Array.isArray(terms)) return []; const ids = []; for (const term of terms) { const normalizedTerm = term.toLowerCase().trim(); const id = mappingObject[normalizedTerm]; if (id !== undefined) { ids.push(id); } } return [...new Set(ids)]; } - index.js:183-188 (helper)Helper function that lazily initializes the AINews client singleton with the provided API key.
function initializeClient(apiKey) { if (!aiNewsClient) { aiNewsClient = new AINews({ apiKey }); } return aiNewsClient; }