首先我们先知道mcp底层会发生什么
底层发生了什么(以windsurf为例)
当你提出问题时:
-
client 将你的问题发送给模型 client可以是市场上支持使用mcp的软件也可以是自己写的client。
-
模型分析可用的 tools 并决定使用哪些 tool 将相关设置设置好模型自己会分析
-
client 通过 MCP server 执行选择的 tool 运行你写的,或者下载的mcp server
-
结果被发回给 模型
-
模型制定自然语言响应
-
响应显示给你!
一,依赖安装
系统要求
-
已安装 Python 3.10 或更高版本。
-
你必须使用 Python MCP SDK 1.2.0 或更高版本。
建议先创建虚拟环境 可以使用uv 也可以使用canda
首先,让我们安装 并设置我们的 Python 项目和环境:uv
# 为我们的项目创建一个新 directory
uv init weather
cd weather
# 创建 virtual environment 并激活它
uv venv
.venv\Scripts\activate
# 安装依赖
uv add mcp[cli] httpx
# 创建我们的 server file
new-item weather.py
二、服务器的搭建
导入包并设置实例
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化 FastMCP server
mcp = FastMCP("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
FastMCP class 使用 Python type hints 和 docstrings 来自动生成 tool definitions,从而轻松创建和维护 MCP tools。
接下来,让我们添加 helper functions,用于查询和格式化来自 National Weather Service API 的数据:
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 None
def format_alert(feature: dict) -> str:
"""将警报 feature 格式化为可读的字符串。"""
props = feature["properties"]
return f"""
事件: {props.get('event', 'Unknown')}
区域: {props.get('areaDesc', 'Unknown')}
严重性: {props.get('severity', 'Unknown')}
描述: {props.get('description', 'No description available')}
指示: {props.get('instruction', 'No specific instructions provided')}
"""
功能解析:
-
异步请求: 使用
httpx.AsyncClient
进行异步 HTTP 请求,这意味着程序可以在等待响应时执行其他任务,提高效率。 -
请求头设置:
-
User-Agent
: 标识请求来源,遵循 NWS API 的使用政策。 -
Accept
: 指定期望的响应格式为 GeoJSON,这是 NWS API 提供地理数据的标准格式。
-
-
错误处理:
-
timeout=30.0
: 设置请求超时时间为 30 秒,防止长时间等待无响应的请求。 -
response.raise_for_status()
: 如果 HTTP 状态码不是 200(成功),会抛出异常。 -
try-except
块捕获所有异常并返回None
,确保函数不会因异常而崩溃。
-
def format_alert(feature: dict) -> str:
"""将警报 feature 格式化为可读的字符串。"""
props = feature["properties"]
return f"""
事件: {props.get('event', 'Unknown')}
区域: {props.get('areaDesc', 'Unknown')}
严重性: {props.get('severity', 'Unknown')}
描述: {props.get('description', 'No description available')}
指示: {props.get('instruction', 'No specific instructions provided')}
"""
功能解析:
-
数据提取:
-
feature["properties"]
: 从 GeoJSON 特性中提取属性字典,包含警报的详细信息。
-
-
格式化输出:
-
使用字典的
.get()
方法安全地获取值,避免因键不存在而引发KeyError
。 -
为每个字段提供默认值(如 "Unknown" 或 "No description available"),确保输出完整。
-
-
信息内容:
-
event
: 警报类型(如 "Severe Thunderstorm Warning")。 -
areaDesc
: 受影响区域的描述。 -
severity
: 严重程度(如 "Severe" 或 "Moderate")。 -
description
: 警报详细描述。 -
instruction
: 建议采取的行动。
-
Tool execution handler 负责实际执行每个 tool 的逻辑。
@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: 位置的经度
"""
# 首先获取预报网格 endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取此位置的预报数据。"
# 从 points response 中获取预报 URL
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预报。"
# 将 periods 格式化为可读的预报
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # 仅显示接下来的 5 个 periods
forecast = f"""
{period['name']}:
温度: {period['temperature']}°{period['temperatureUnit']}
风: {period['windSpeed']} {period['windDirection']}
预报: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
最后,让我们初始化并运行 server:
if __name__ == "__main__":
# 初始化并运行 server
mcp.run(transport='stdio')
三、windsurf(编程软件)配置。
项目运行需要魔法
将上面所有代码粘贴进创建的文件夹内。
点击对话框边上的
会进入一个js文件,然后进行配置。配置参数如下,使用uv运行,修改自己的文件路径。
点击refresh就会显示mcp文件数量,在对话框输入相关消息模型自动会获取天气信息。如下图: