| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- from __future__ import annotations
- from fastapi import FastAPI
- from mcp.server.fastmcp import FastMCP
- from mcp.server.transport_security import TransportSecuritySettings
- from news_mcp.config import CLUSTERS_TTL_HOURS, DEFAULT_TOPICS, DB_PATH
- from news_mcp.jobs.poller import refresh_clusters
- from news_mcp.storage.sqlite_store import SQLiteClusterStore
- mcp = FastMCP(
- "news-mcp",
- transport_security=TransportSecuritySettings(enable_dns_rebinding_protection=False),
- )
- @mcp.tool(description="What is happening right now? Return the latest deduplicated news clusters for a topic.")
- async def get_latest_events(topic: str = "crypto", limit: int = 5):
- limit = max(1, min(int(limit), 20))
- # Refresh opportunistically (v1 simple: refresh every call but bounded to small RSS pull)
- refresh_clusters(topic=topic, limit=50)
- store = SQLiteClusterStore(DB_PATH)
- clusters = store.get_latest_clusters(topic=topic, ttl_hours=CLUSTERS_TTL_HOURS, limit=limit)
- # Ensure the response is compact and agent-friendly.
- out = []
- for c in clusters:
- out.append(
- {
- "cluster_id": c.get("cluster_id"),
- "headline": c.get("headline"),
- "summary": c.get("summary"),
- "entities": c.get("entities", []),
- "sentiment": c.get("sentiment", "neutral"),
- "importance": c.get("importance", 0.0),
- "sources": c.get("sources", []),
- "timestamp": c.get("timestamp"),
- }
- )
- return out
- app = FastAPI(title="News MCP Server")
- app.mount("/mcp", mcp.sse_app())
- @app.get("/")
- def root():
- return {"status": "ok", "transport": "fastmcp+sse", "mount": "/mcp", "tools": ["get_latest_events"]}
- @app.get("/health")
- def health():
- return {"status": "ok", "ttl_hours": CLUSTERS_TTL_HOURS, "db": str(DB_PATH)}
|