开始构建你自己的服务器,以在 Claude for Desktop 和其他客户端中使用
在本教程中,我们将构建一个简单的 MCP 天气服务器,并将其连接到主机——Claude for Desktop。我们将从基本设置开始,然后逐步拓展到更复杂的用例。
我们要构建什么?
许多 LLM(包括 Claude)目前无法获取天气预报和严重天气警报。让我们使用 MCP 来解决这个问题!
我们将构建一个服务器,公开两个工具:get-alerts
和 get-forecast
,然后将服务器连接到 MCP 主机(在本例中是 Claude for Desktop):
服务器可以连接到任何客户端。这里我们选择 Claude for Desktop 只是为了简化流程,同时我们还提供了 构建你自己的客户端 的指南,以及其他客户端的列表。
为什么选择 Claude for Desktop 而不是 Claude.ai?
因为服务器是在本地运行的,而 MCP 目前仅支持桌面端主机。远程主机的支持正在开发中。
MCP 核心概念
MCP 服务器可以提供三种主要的功能:
- 资源(Resources):客户端可以读取的类似文件的数据(例如 API 响应或文件内容)。
- 工具(Tools):LLM 可以调用的函数(需要用户批准)。
- 提示(Prompts):帮助用户完成特定任务的预设模板。
本教程主要关注 工具(Tools)。
先决知识
本快速入门教程假设你熟悉以下内容:
- Python
- LLM(如 Claude)
系统要求
- 安装 Python 3.10 或更高版本。
- 你需要使用 Python MCP SDK 1.2.0 或更高版本。
设置开发环境
首先,我们需要安装 uv
并设置 Python 项目和环境:
MacOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
请确保在安装后重启终端,以便 uv
命令能够被识别。
然后,创建并设置我们的项目:
# 创建新项目目录
uv init weather
cd weather
# 创建虚拟环境并激活
uv venv
source .venv/bin/activate
# 安装依赖
uv add "mcp[cli]" httpx
# 创建服务器文件
touch weather.py
构建你的服务器
导入必要的包并初始化 MCP 实例
在 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"
FastMCP
类使用 Python 类型提示和文档字符串自动生成工具定义,使得创建和维护 MCP 工具变得更加简单。
编写辅助函数
接下来,我们添加用于从美国国家气象局(NWS)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:
"""将天气警报格式化为可读的字符串"""
props = feature["properties"]
return f"""
事件: {props.get('event', '未知')}
地区: {props.get('areaDesc', '未知')}
严重程度: {props.get('severity', '未知')}
描述: {props.get('description', '无描述')}
指引: {props.get('instruction', '无具体指引')}
"""
实现工具方法
工具执行处理程序负责执行工具的具体逻辑。我们添加以下两个方法:
@mcp.tool()
async def get_alerts(state: str) -> str:
"""获取某个美国州的天气警报。
参数:
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:
"""获取指定位置的天气预报。
参数:
latitude: 纬度
longitude: 经度
"""
# 获取天气预报的 API 端点
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取该位置的天气预报数据。"
# 获取天气预报 URL
forecast_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']}:
温度: {period['temperature']}°{period['temperatureUnit']}
风速: {period['windSpeed']} {period['windDirection']}
天气: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
运行服务器
最后,我们初始化并运行服务器:
if __name__ == "__main__":
mcp.run(transport='stdio')
你的服务器现在已经完成!运行以下命令来确认是否正常工作:
uv run weather.py
在 Claude for Desktop 上测试你的服务器
- 安装 Claude for Desktop(下载最新版本)。
- 配置 Claude for Desktop 以使用 MCP 服务器。在
~/Library/Application Support/Claude/claude_desktop_config.json
中添加以下内容:
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
- 重启 Claude for Desktop,然后你应该能在工具栏看到 MCP 工具的图标。
MCP 工作原理
当你向 Claude for Desktop 询问天气时:
- 客户端将你的问题发送给 Claude。
- Claude 识别并选择合适的 MCP 工具。
- 客户端通过 MCP 服务器执行该工具。
- 服务器返回查询结果。
- Claude 处理并生成自然语言回复。
- 你在 Claude for Desktop 上看到结果!
这样,你的 MCP 天气服务器就成功构建并集成到 Claude for Desktop 了! 🎉