uv运行一个MCP Server的完整流程
uv是一个高性能的Python包管理器,专注于性能提升。与pip相比,uv利用全局模块缓存,减少磁盘空间使用,并支持Linux、Windows和macOS系统。安装uv可以通过多种方式实现,例如使用Homebrew、Pacman、pip等。
step 1 安装uv:
pip install uv
step 2 初始化项目:
uv init weather
step 3 进入项目目录:
cd weather
step 4 下载python环境:
uv add python 3.11
step 5 生成uv虚拟环境:
uv venv
source .venv/bin/activate 【For MAC】
or
source .venv\Scripts\activate 【For Win】
step 6 切换uv虚拟环境:
uv python pin 3.11
step 7: 写stdio的MCP Server逻辑 vim weather.py
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP# 初始化 FastMCP 服务器
mcp = FastMCP("weather")NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"async def make_nws_request(url: str) -> dict[str, Any] | None:"""向 NWS API 发送请求并进行适当的错误处理。"""headers = {"User-Agent": USER_AGENT,"Accept": "application/geo+json"}async with httpx.AsyncClient() as client:try:response = await client.get(url, headers=headers, timeout=30.0)response.raise_for_status()return response.json()except Exception:return Nonedef format_alert(feature: dict) -> str:"""将警报特征格式化为可读字符串。"""props = feature["properties"]return f"""
Event: {props.get('event', 'Unknown')}
Area: {props.get('areaDesc', 'Unknown')}
Severity: {props.get('severity', 'Unknown')}
Description: {props.get('description', 'No description available')}
Instructions: {props.get('instruction', 'No specific instructions provided')}
"""@mcp.tool()
async def get_alerts(state: str) -> str:"""获取美国州的天气警报。Args:state: 美国州的两字母代码(例如 CA, NY)"""url = f"{NWS_API_BASE}/alerts/active/area/{state}"data = await make_nws_request(url)if not data or "features" not in data:return "无法获取警报或未找到警报。"if not data["features"]:return "该州没有活跃警报。"alerts = [format_alert(feature) for feature in data["features"]]return "\n---\n".join(alerts)@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:"""获取某个位置的天气预报。Args:latitude: 位置的纬度longitude: 位置的经度"""# 首先获取预报网格端点points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"points_data = await make_nws_request(points_url)if not points_data:return "无法获取该位置的预报数据。"# 从 points 响应获取预报 URLforecast_url = points_data["properties"]["forecast"]forecast_data = await make_nws_request(forecast_url)if not forecast_data:return "无法获取详细预报。"# 将周期格式化为可读的预报periods = forecast_data["properties"]["periods"]forecasts = []for period in periods[:5]: # 仅显示接下来的 5 个周期forecast = f"""
{period['name']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""forecasts.append(forecast)return "\n---\n".join(forecasts)if __name__ == "__main__":# 初始化并运行服务器mcp.run(transport='stdio')
step 8: uv run weather.py