huggingface_trending
Browse Hugging Face Hub to find trending models, datasets, and spaces. Filter by sort order, time range, and query to discover popular or recent content.
Instructions
Browse Hugging Face Hub. kind selects models / datasets / spaces (default models). sort: trending / downloads / likes / recent. days filters by lastModified — CAUTION: this catches old entries with recent edits, not just newly published ones. For 'truly new' discovery prefer sort='recent' + days=N.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | models | |
| sort | No | trending | |
| query | No | ||
| tag | No | ||
| days | No | ||
| max_results | No | ||
| response_format | No | markdown |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- trends_mcp.py:978-986 (schema)HFTrendingInput Pydantic model — input schema for the huggingface_trending tool. Defines fields: kind (models/datasets/spaces), sort (trending/downloads/likes/recent), query, tag, days, max_results, response_format.
class HFTrendingInput(BaseModel): model_config = ConfigDict(str_strip_whitespace=True, extra="forbid") kind: str = Field("models", pattern=r"^(models|datasets|spaces)$") sort: str = Field("trending", pattern=r"^(trending|downloads|likes|recent)$") query: str | None = Field(None, max_length=200) tag: str | None = Field(None, max_length=80) days: int | None = Field(None, ge=1, le=3650, description="If set, drop entries whose lastModified is older than N days.") max_results: int = Field(20, ge=1, le=50) response_format: ResponseFormat = ResponseFormat.MARKDOWN - trends_mcp.py:1024-1040 (registration)Registration of huggingface_trending as an MCP tool via the @_maybe_tool decorator with source='huggingface'. This decorator conditionally registers the tool with FastMCP only if the 'huggingface' source is enabled.
@_maybe_tool( source="huggingface", name="huggingface_trending", description=( "Browse Hugging Face Hub. `kind` selects models / datasets / spaces " "(default models). `sort`: trending / downloads / likes / recent. " "`days` filters by `lastModified` — CAUTION: this catches old entries " "with recent edits, not just newly published ones. For 'truly new' " "discovery prefer sort='recent' + days=N." ), annotations={ "readOnlyHint": True, "destructiveHint": False, "openWorldHint": True, "idempotentHint": False, }, ) - trends_mcp.py:1041-1127 (handler)Main handler function for huggingface_trending. Calls the Hugging Face Hub API (HF_API/{kind}) with sort, direction, limit, search, and filter params. Supports over-fetching for date filtering, constructs proper URLs per kind (models/datasets/spaces), and returns formatted markdown or JSON output.
async def huggingface_trending( kind: str = "models", sort: str = "trending", query: str | None = None, tag: str | None = None, days: int | None = None, max_results: int = 20, response_format: ResponseFormat = ResponseFormat.MARKDOWN, ) -> str: try: args = HFTrendingInput( kind=kind, sort=sort, query=query, tag=tag, days=days, max_results=max_results, response_format=response_format, ) url = f"{HF_API}/{args.kind}" # Over-fetch when filtering by days, since HF API has no date filter. fetch_n = min(args.max_results * (5 if args.days else 1), 200) params: dict[str, Any] = { "sort": _HF_SORT_MAP[args.sort], "direction": -1, "limit": fetch_n, } if args.query: params["search"] = args.query if args.tag: params["filter"] = args.tag headers: dict[str, str] = {} token = os.environ.get("HF_TOKEN") if token: headers["Authorization"] = f"Bearer {token}" ttl = TTL_TRENDING if args.sort == "trending" else TTL_DEFAULT raw = await _http_get_json(url, params=params, headers=headers or None, ttl=ttl) if not isinstance(raw, list): raw = [] cutoff = _utc_now() - timedelta(days=args.days) if args.days else None items: list[dict[str, Any]] = [] for r in raw: last_mod = r.get("lastModified") or r.get("last_modified") if cutoff: if not last_mod: continue try: lm_dt = datetime.fromisoformat(str(last_mod).replace("Z", "+00:00")) if lm_dt.tzinfo is None: lm_dt = lm_dt.replace(tzinfo=timezone.utc) except ValueError: continue if lm_dt < cutoff: continue rid = r.get("id") or r.get("modelId") or "" if args.kind == "models": disp_url = f"https://huggingface.co/{rid}" elif args.kind == "datasets": disp_url = f"https://huggingface.co/datasets/{rid}" else: disp_url = f"https://huggingface.co/spaces/{rid}" items.append( { "id": rid, "url": disp_url, "downloads": r.get("downloads"), "likes": r.get("likes", 0), "lastModified": last_mod, "tags": r.get("tags") or [], "pipeline_tag": r.get("pipeline_tag"), "library_name": r.get("library_name"), "sdk": r.get("sdk"), "task_categories": r.get("task_categories") or [], } ) if len(items) >= args.max_results: break header = f"Hugging Face {args.kind} — {args.sort}" if args.query: header += f" · `{args.query}`" if args.tag: header += f" · #{args.tag}" if args.days: header += f" · 최근 {args.days}일" return _format(items, args.response_format, render_md=lambda x: _render_hf_md(x, header, args.kind)) except Exception as e: return _handle_error(e, "huggingface_trending") - trends_mcp.py:989-994 (helper)Maps friendly sort names ('trending', 'downloads', 'likes', 'recent') to Hugging Face API sort parameters ('trendingScore', 'downloads', 'likes', 'lastModified').
_HF_SORT_MAP = { "trending": "trendingScore", "downloads": "downloads", "likes": "likes", "recent": "lastModified", } - trends_mcp.py:997-1021 (helper)Renders Hugging Face items in Markdown format. Shows downloads count, likes, lastModified date, pipeline_tag for models, sdk for spaces, and up to 6 tags.
def _render_hf_md(items: list[dict[str, Any]], header: str, kind: str) -> str: if not items: return f"# {header}\n\n_결과 없음_" lines = [f"# {header}", f"_총 {len(items)}건_", ""] for i, it in enumerate(items, 1): bits: list[str] = [] if it.get("downloads") is not None: bits.append(f"📥 {it['downloads']:,}") bits.append(f"❤️ {it.get('likes', 0):,}") if it.get("lastModified"): bits.append(f"업데이트 {_fmt_date(it['lastModified'])}") meta = " · ".join(bits) sub = "" if kind == "models" and it.get("pipeline_tag"): sub = f" · `{it['pipeline_tag']}`" if kind == "spaces" and it.get("sdk"): sub = f" · `{it['sdk']}`" tags = it.get("tags") or [] tag_line = ", ".join(tags[:6]) lines.append( f"## {i}. [{it['id']}]({it['url']}){sub}\n" f"- {meta}\n" + (f"- 태그: {tag_line}\n" if tag_line else "") ) return "\n".join(lines)