Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Access CoinGecko crypto market data: spot prices, OHLC, trending coins, exchange listings, NFTs, and global stats.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
tools/market_discovery.py
1#!/usr/bin/env python32"""3CoinGecko Market Discovery Tools45Tools for discovering trending coins, top movers, and newly listed coins.6"""78import os9from dotenv import load_dotenv10import json11import argparse12from typing import Dict, Any1314from core.http_client import proxied_get1516# Load environment variables17load_dotenv()181920# MCP Tool Schemas21MCP_TRENDING_SCHEMA = {22"name": "cg_trending",23"title": "CoinGecko Trending Coins",24"description": "Get trending coins in the last 24 hours based on user search data.",25"inputSchema": {26"type": "object",27"properties": {},28"additionalProperties": False29}30}3132MCP_TOP_GAINERS_LOSERS_SCHEMA = {33"name": "cg_top_gainers_losers",34"title": "CoinGecko Top Gainers/Losers",35"description": "Get top 30 gainers and losers by price change percentage.",36"inputSchema": {37"type": "object",38"properties": {39"vs_currency": {40"type": "string",41"description": "Target currency for price data",42"default": "usd"43},44"duration": {45"type": "string",46"description": "Time duration: 1h, 24h, 7d, 14d, 30d, 60d, 1y",47"default": "24h",48"enum": ["1h", "24h", "7d", "14d", "30d", "60d", "1y"]49}50},51"additionalProperties": False52}53}5455MCP_NEW_COINS_SCHEMA = {56"name": "cg_new_coins",57"title": "CoinGecko Recently Added Coins",58"description": "Get recently added coins to CoinGecko.",59"inputSchema": {60"type": "object",61"properties": {},62"additionalProperties": False63}64}656667def get_api_key() -> str:68"""Get CoinGecko API key from environment."""69api_key = os.getenv("COINGECKO_API_KEY")70if not api_key:71raise ValueError("COINGECKO_API_KEY environment variable is required")72return api_key737475def get_trending() -> Dict[str, Any]:76"""77Get trending coins in the last 24 hours.7879Based on user search data on CoinGecko.8081Returns:82Dictionary with trending coins, nfts, and categories83"""84api_key = get_api_key()8586url = "https://pro-api.coingecko.com/api/v3/search/trending"87headers = {"x-cg-pro-api-key": api_key}8889response = proxied_get(url, headers=headers, timeout=15)90response.raise_for_status()91data = response.json()9293# Format coins94trending_coins = []95for item in data.get("coins", []):96coin = item.get("item", {})97trending_coins.append({98"rank": coin.get("score", 0) + 1,99"id": coin.get("id", ""),100"symbol": coin.get("symbol", "").upper(),101"name": coin.get("name", ""),102"market_cap_rank": coin.get("market_cap_rank"),103"price_btc": coin.get("price_btc"),104"price_change_24h": coin.get("data", {}).get("price_change_percentage_24h", {}).get("usd"),105"market_cap": coin.get("data", {}).get("market_cap"),106"total_volume": coin.get("data", {}).get("total_volume"),107"sparkline": coin.get("data", {}).get("sparkline")108})109110# Format NFTs111trending_nfts = []112for nft in data.get("nfts", []):113trending_nfts.append({114"id": nft.get("id", ""),115"name": nft.get("name", ""),116"symbol": nft.get("symbol", ""),117"floor_price_24h_change": nft.get("floor_price_24h_percentage_change")118})119120# Format categories121trending_categories = []122for cat in data.get("categories", []):123trending_categories.append({124"id": cat.get("id"),125"name": cat.get("name", ""),126"market_cap_change_24h": cat.get("market_cap_1h_change")127})128129return {130"coins": trending_coins,131"nfts": trending_nfts,132"categories": trending_categories133}134135136def get_top_gainers_losers(137vs_currency: str = "usd",138duration: str = "24h"139) -> Dict[str, Any]:140"""141Get top 30 gainers and losers by price change percentage.142143Args:144vs_currency: Target currency (usd, eur, btc)145duration: Time duration (1h, 24h, 7d, 14d, 30d, 60d, 1y)146147Returns:148Dictionary with top_gainers and top_losers lists149"""150api_key = get_api_key()151152url = "https://pro-api.coingecko.com/api/v3/coins/top_gainers_losers"153headers = {"x-cg-pro-api-key": api_key}154params = {155"vs_currency": vs_currency,156"duration": duration157}158159response = proxied_get(url, headers=headers, params=params, timeout=15)160response.raise_for_status()161data = response.json()162163# Format gainers164gainers = []165for coin in data.get("top_gainers", []):166gainers.append({167"id": coin.get("id", ""),168"symbol": coin.get("symbol", "").upper(),169"name": coin.get("name", ""),170"image": coin.get("image", ""),171"price": coin.get(vs_currency),172"price_change_percentage": coin.get(f"{vs_currency}_24h_change")173})174175# Format losers176losers = []177for coin in data.get("top_losers", []):178losers.append({179"id": coin.get("id", ""),180"symbol": coin.get("symbol", "").upper(),181"name": coin.get("name", ""),182"image": coin.get("image", ""),183"price": coin.get(vs_currency),184"price_change_percentage": coin.get(f"{vs_currency}_24h_change")185})186187return {188"vs_currency": vs_currency,189"duration": duration,190"top_gainers": gainers,191"top_losers": losers192}193194195def get_new_coins() -> Dict[str, Any]:196"""197Get recently added coins to CoinGecko.198199Returns:200Dictionary with list of newly added coins201"""202api_key = get_api_key()203204url = "https://pro-api.coingecko.com/api/v3/coins/list/new"205headers = {"x-cg-pro-api-key": api_key}206207response = proxied_get(url, headers=headers, timeout=15)208response.raise_for_status()209data = response.json()210211coins = []212for coin in data:213coins.append({214"id": coin.get("id", ""),215"symbol": coin.get("symbol", "").upper(),216"name": coin.get("name", ""),217"activated_at": coin.get("activated_at")218})219220return {221"new_coins": coins,222"count": len(coins)223}224225226def main():227"""CLI interface for market discovery tools."""228parser = argparse.ArgumentParser(229description="CoinGecko Market Discovery Tools",230formatter_class=argparse.RawDescriptionHelpFormatter231)232233subparsers = parser.add_subparsers(dest="command")234235# Trending command236subparsers.add_parser("trending", help="Get trending coins")237238# Gainers/losers command239gl_parser = subparsers.add_parser("gainers-losers", help="Get top gainers and losers")240gl_parser.add_argument("--currency", default="usd")241gl_parser.add_argument(242"--duration", default="24h",243choices=["1h", "24h", "7d", "14d", "30d", "60d", "1y"]244)245246# New coins command247subparsers.add_parser("new", help="Get newly added coins")248249parser.add_argument("--schema", action="store_true", help="Output MCP schema")250251args = parser.parse_args()252253if args.schema:254schemas = {255"trending": MCP_TRENDING_SCHEMA,256"top_gainers_losers": MCP_TOP_GAINERS_LOSERS_SCHEMA,257"new_coins": MCP_NEW_COINS_SCHEMA258}259print(json.dumps(schemas, indent=2))260return 0261262try:263if args.command == "trending":264result = get_trending()265elif args.command == "gainers-losers":266result = get_top_gainers_losers(args.currency, args.duration)267elif args.command == "new":268result = get_new_coins()269else:270parser.print_help()271return 0272273print(json.dumps(result, indent=2, ensure_ascii=False))274return 0275276except Exception as e:277print(json.dumps({"error": str(e)}, indent=2))278return 1279280281if __name__ == "__main__":282exit(main())283