bestgithub / app.py
tianruci's picture
Update app.py
49846c3 verified
import os
import json
import httpx
from fastapi import FastAPI, HTTPException, APIRouter
from datetime import datetime, timedelta
from fastapi.middleware.cors import CORSMiddleware
from fastmcp.server import FastMCP
from contextlib import asynccontextmanager
from typing import List, Dict, Optional
# 初始化 MCP 服务器(必须在 FastAPI 之前)
mcp_server = FastMCP(name="GitHubTrendingAPI")
@asynccontextmanager
async def lifespan(app: FastAPI):
await fetch_github_trending()
yield
app = FastAPI(lifespan=lifespan)
# CORS 配置
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 缓存变量
cached_trending = []
last_updated = None
async def fetch_github_trending():
global cached_trending, last_updated
headers = {"Accept": "application/vnd.github.v3+json"}
if token := os.getenv("GITHUB_TOKEN"):
headers["Authorization"] = f"token {token}"
try:
async with httpx.AsyncClient() as client:
r = await client.get(
"https://api.github.com/search/repositories",
params={"q": "stars:>1000", "sort": "stars", "per_page": 10},
headers=headers
)
r.raise_for_status()
cached_trending = [
{
"name": repo["full_name"],
"url": repo["html_url"],
"stars": repo["stargazers_count"]
}
for repo in r.json()["items"]
]
last_updated = datetime.now()
except Exception as e:
print(f"Fetch error: {e}")
if not cached_trending:
raise HTTPException(500, "Failed to fetch data")
@mcp_server.tool()
async def get_trending_repos(num: int = 10) -> dict:
if not last_updated or (datetime.now() - last_updated) > timedelta(minutes=30):
await fetch_github_trending()
return {"trending": cached_trending[:num]}
# 关键修改:正确挂载MCP路由
# 方案1:直接挂载整个MCP应用
app.mount("/mcp", mcp_server.http_app())
# 方案2:或者使用APIRouter(如果方案1不行)
# mcp_router = APIRouter()
# mcp_router.include_router(mcp_server.http_app().router, prefix="")
# app.include_router(mcp_router, prefix="/mcp")
# 添加MCP健康检查路由
@app.get("/mcp/health")
async def mcp_health_check():
return {"status": "ok", "mcp_version": "1.0"}
@app.get("/")
async def root():
# 添加更多有用的调试信息
return {
"message": "API is running",
"endpoints": {
"mcp_tool": "/mcp/tool/get_trending_repos",
"mcp_schema": "/mcp/schema",
"mcp_health": "/mcp/health",
"trending": "/trending"
}
}
@app.get("/trending")
async def get_trending(num: int = 10):
if not cached_trending:
await fetch_github_trending()
return {"trending": cached_trending[:num]}
# 在app.py中添加
@app.get("/mcp/")
async def mcp_root():
return {
"message": "MCP API root",
"endpoints": {
"tools": "/mcp/tool",
"schema": "/mcp/schema"
}
}