1.构建一个MCP服务器 #
本教程将指导您构建一个简单的MCP天气服务器,并将其连接到Claude for Desktop。我们将从基础设置开始,逐步过渡到更复杂的应用场景。
2.我们将要构建的内容 #
目前许多大型语言模型(LLM)尚不具备获取天气预报和恶劣天气警报的能力。让我们用MCP(Model Context Protocol)来解决这个问题吧!
我们将构建一个服务器,对外提供两个工具:
get_alerts- 获取天气警报get_forecast- 获取天气预报
接着我们将服务器连接到一个MCP主机(本例中使用的是Claude for Desktop):


注意:服务器可以连接任何客户端。这里我们选择Claude for Desktop是为了简化操作,不过我们也提供了关于构建你自己的客户端以及一个此处列出其他客户名单。
3.MCP核心概念 #
MCP服务器可提供三大主要功能类型:
- 资源 - 可供客户端读取的类文件数据(如API响应或文件内容)
- 工具 - 可由LLM(经用户批准后)调用的函数
- 提示词 - 预先编写好的模板,帮助用户完成特定任务
4.开始构建 #
让我们开始构建我们的天气服务器吧!你可以在这里找到我们将要构建的完整代码。
4.1 先决知识 #
本快速入门指南假定您已熟悉以下内容:
- Python
- 像Claude这样的LLMs
4.2 MCP服务器中的日志记录 #
在实现MCP服务器时,务必谨慎处理日志记录的方式:
对于基于STDIO的服务器: 切勿写入标准输出(stdout)。这包括:
print()Python中的语句console.log()在JavaScript中fmt.Println()在Go语言中- 其他语言中类似的stdout功能
写入stdout会破坏JSON-RPC消息并导致服务器崩溃。
对于基于HTTP的服务器: 标准输出日志记录没有问题,因为它不会干扰HTTP响应。
4.3 最佳实践 #
- 使用一个将日志写入stderr或文件的logging库。
4.4 快速示例 #
# Bad (STDIO)
print("Processing request")
# Good (STDIO)
import logging
logging.info("Processing request")4.5 系统要求 #
- 已安装 Python 3.10 或更高版本
- 你必须使用Python MCP SDK 1.2.0或更高版本
4.6 设置您的环境 #
首先,让我们安装uv并设置我们的Python项目和环境:
MacOS/Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh确保之后重启终端以保证uv命令被接收。
现在,让我们创建并设置我们的项目:
MacOS/Linux:
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]" httpx
# Create our server file
touch weather.py现在让我们深入探讨如何构建你的服务器。
5.构建你的服务器 #
# 导入Any类型用于类型注解
from typing import Any
# 导入httpx库用于异步HTTP请求
import httpx
# 从mcp.server.fastmcp模块导入FastMCP类
from mcp.server.fastmcp import FastMCP
# 定义NWS(美国国家气象局)API的基础URL
NWS_API_BASE = "https://api.weather.gov"
# 定义请求头中的User-Agent
USER_AGENT = "weather-app/1.0"
# 异步函数,向NWS API发起请求并处理异常
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""向NWS API发起请求并进行错误处理。"""
# 设置请求头,包含User-Agent和Accept
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
# 创建异步HTTP客户端
async with httpx.AsyncClient() as client:
try:
# 发送GET请求,设置超时时间为30秒
response = await client.get(url, headers=headers, timeout=30.0)
# 检查响应状态码,若有异常则抛出
response.raise_for_status()
# 返回响应的JSON内容
return response.json()
except Exception:
# 捕获所有异常,返回None
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', '暂无具体指引')}
"""
# 初始化FastMCP服务器,服务名为"weather"
mcp = FastMCP("weather")
# 注册为MCP工具,获取指定州的气象预警信息
@mcp.tool()
async def get_alerts(state: str) -> str:
"""获取美国某州的气象预警信息。
参数:
state: 美国州的两位字母代码(如 CA, NY)
"""
# 构造API请求URL
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
# 异步获取数据
data = await make_nws_request(url)
# 如果数据为空或不包含features字段,返回错误信息
if not data or "features" not in data:
return "无法获取预警信息或未找到相关预警。"
# 如果features为空列表,说明当前无有效预警
if not data["features"]:
return "该州当前无有效预警。"
# 遍历所有预警信息,格式化输出
alerts = [format_alert(feature) for feature in data["features"]]
# 用分隔符拼接所有预警信息
return "\n---\n".join(alerts)
# 注册为MCP工具,获取指定经纬度的天气预报
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""获取指定位置的天气预报。
参数:
latitude: 位置的纬度
longitude: 位置的经度
"""
# 构造获取网格点信息的API URL
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 = []
# 遍历前5个预报时段
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__":
# 初始化并运行服务器,使用stdio作为传输方式
mcp.run(transport="stdio")
您的服务器已准备就绪!运行uv run weather.py启动MCP服务器,该服务器将监听来自MCP主机的消息。
现在让我们从现有的MCP主机Claude for Desktop测试你的服务器。
6.使用Claude for Desktop测试您的服务器 #
注意: Claude for Desktop 目前尚未支持 Linux 系统。Linux 用户可前往构建一个客户端教程:构建一个连接到我们刚搭建的服务器的MCP客户端。
6.1 安装和配置 #
首先,确保你已安装Claude for Desktop。您可以在此处安装最新版本。如果你已经安装了Claude for Desktop,确保它已更新至最新版本。
我们需要为你想使用的MCP服务器配置Claude for Desktop。为此,请打开你的Claude for Desktop应用程序配置。~/Library/Application Support/Claude/claude_desktop_config.json在文本编辑器中。确保如果文件不存在则创建它。
例如,如果你有VS Code已安装:
# MacOS/Linux
code ~/Library/Application\ Support/Claude/claude_desktop_config.json接着你将添加你的servers到mcpServers密钥。MCP UI元素仅当至少正确配置了一台服务器时,才会在Claude for Desktop中显示。
在这种情况下,我们将像这样添加我们的单一天气服务器:
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}警告: 你可能需要输入完整路径到
uv可执行文件中的command字段。您可以通过运行获取此信息which uv在MacOS/Linux或where uv在Windows上。
提示: 确保传入服务器的绝对路径。你可以通过运行以下命令获取该路径:
pwd在MacOS/Linux或cd在Windows命令提示符下。在Windows上,记得使用双反斜杠(\\) 或正斜杠 (/) 在JSON路径中。
这告诉Claude for Desktop:
- 有一个名为"weather"的MCP服务器
- 通过运行来启动它
uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py
保存文件并重新启动桌面版Claude。
6.2 使用命令进行测试 #
让我们确保Claude for Desktop能识别我们已公开的这两个工具。weather服务器。你可以通过查找"搜索和工具"图标来完成此操作。

点击滑块图标后,您应该会看到列出的两个工具:

如果您的服务器未被Claude for Desktop检测到,请继续故障排除调试技巧专区。
如果工具设置图标已显示,你现在可以通过在Claude for Desktop中运行以下命令来测试你的服务器:
- 萨克拉门托的天气怎么样?
- 德克萨斯州有哪些活跃的天气警报?


注意: 由于这是美国国家气象局服务,查询仅适用于美国境内地点。
7.幕后发生了什么 #
当你提问时:
- 客户端将您的问题发送给Claude
- Claude分析可用的工具并决定使用其中的哪一个(些)
- 客户端通过MCP服务器执行选定的工具
- 结果被发送回Claude
- Claude 生成自然语言回复
- 响应已显示给您!
8.故障排除 #
8.1 Claude桌面集成问题 #
8.1.1 从Claude for Desktop获取日志 #
与MCP相关的Claude.app日志记录会被写入到log文件中~/Library/Logs/Claude:
mcp.log将包含关于MCP连接及连接失败的一般日志记录- 文件名为
mcp-server-SERVERNAME.log将包含来自指定服务器的错误(stderr)日志记录
你可以运行以下命令来列出最近的日志并实时跟踪新产生的日志:
# 检查Claude的日志错误
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log8.1.2 Claude中未显示服务器 #
- 检查你的
claude_desktop_config.json文件语法 - 确保你的项目路径是绝对路径而非相对路径
- 完全重启Claude for Desktop
8.1.3 工具调用静默失败 #
如果Claude尝试使用工具但失败了:
- 检查Claude的日志以查找错误
- 验证您的服务器构建并运行无误
- 尝试重启Claude for Desktop
8.1.4 这完全不管用,我该怎么办? #
请参考我们的调试指南为了更好的调试工具和更详细的指导。
8.2 天气API问题 #
8.2.1 Error: Failed to retrieve grid point data #
这通常意味着以下两种情况之一:
- 坐标位于美国境外
- NWS API 出现问题
- 您被限速了
修复:
- 确认您使用的是US坐标
- 在请求之间添加短暂延迟
- 查看NWS API状态页面
8.2.2 Error: No active alerts for [STATE] #
这不是错误——只是表示该州当前没有天气警报。请尝试查询其他州或在恶劣天气期间再次检查。
提示: 如需更高级的故障排除,请查阅我们的指南调试MCP