Skip to main content
在本教程中,我们将构建一个简单的 MCP 天气服务器,并将其连接到宿主——Claude for Desktop。我们将从基础设置开始,然后逐步扩展到更复杂的用例。

我们将构建什么

目前,许多大语言模型尚无法获取天气预报和严重天气警报。让我们借助 MCP 来解决这一问题! 我们将构建一个服务器,公开两个工具:get_alertsget_forecast。随后,将该服务器连接到 MCP 宿主(本例中为 Claude for Desktop):
服务器可以连接到任何客户端。此处我们选择 Claude for Desktop 以简化流程,但我们也提供了构建自有客户端的指南,以及其他客户端列表

MCP 核心概念

MCP 服务器可提供三种主要能力:
  1. 资源:可被客户端读取的类文件数据(如 API 响应或文件内容)
  2. 工具:可由 LLM 调用的函数(需用户批准)
  3. 提示:帮助用户完成特定任务的预编写模板
本教程主要聚焦于工具。
让我们开始构建天气服务器!可在此处找到我们将构建的完整代码。

前置知识

本快速入门假设你已熟悉:
  • Python
  • Claude 等 LLM

MCP 服务器中的日志记录

在实现 MCP 服务器时,请谨慎处理日志记录:对于基于 STDIO 的服务器: 切勿写入标准输出(stdout)。这包括:
  • Python 中的 print() 语句
  • JavaScript 中的 console.log()
  • Go 中的 fmt.Println()
  • 其他语言中类似的 stdout 函数
写入 stdout 会破坏 JSON-RPC 消息,导致服务器失效。对于基于 HTTP 的服务器: 标准输出日志记录是可接受的,因为它不会干扰 HTTP 响应。

最佳实践

  1. 使用写入 stderr 或文件的日志库。

快速示例

# ❌ 不好的做法(STDIO)
print("正在处理请求")

# ✅ 好的做法(STDIO)
import logging
logging.info("正在处理请求")

系统要求

  • 已安装 Python 3.10 或更高版本。
  • 必须使用 Python MCP SDK 1.2.0 或更高版本。

配置环境

首先,安装 uv 并设置我们的 Python 项目及环境:
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
现在让我们深入构建你的服务器。

构建你的服务器

导入包并设置实例

将这些内容添加到你的 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 工具变得简单。

辅助函数

接下来,我们添加用于查询并格式化来自国家气象局 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:
    """获取美国某州的天气预警。

    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 响应中获取预报 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 来启动 MCP 服务器,它将监听来自 MCP 主机的消息。现在,让我们用现有的 MCP 主机——Claude for Desktop——来测试你的服务器。

使用 Claude for Desktop 测试你的服务器

Claude for Desktop 尚未在 Linux 上推出。Linux 用户可以跳转到构建客户端教程,构建一个连接到刚才所建服务器的 MCP 客户端。
首先,请确保你已安装 Claude for Desktop。可在此处安装最新版本。 如果你已经安装了 Claude for Desktop,请确保更新到最新版本。我们需要为要使用的任何 MCP 服务器配置 Claude for Desktop。为此,请在文本编辑器中打开 Claude for Desktop 应用配置:~/Library/Application Support/Claude/claude_desktop_config.json。如果该文件不存在,请务必创建它。例如,如果你已安装 VS Code
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
接下来在 mcpServers 键里添加服务器。只有当至少一个服务器正确配置后,MCP 的 UI 元素才会在 Claude for Desktop 里出现。此时我们像这样添加单个天气服务器:
{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
        "run",
        "weather.py"
      ]
    }
  }
}
你可能需要在 command 字段中填写 uv 可执行文件的完整路径。你可以通过运行 which uv(macOS/Linux)或 where uv(Windows)来获取。
请确保传入服务器的绝对路径。你可以通过运行 pwd(macOS/Linux)或 cd(Windows 命令提示符)来获取。在 Windows 上,请记得在 JSON 路径中使用双反斜杠(\\)或正斜杠(/)。
这告诉 Claude for Desktop:
  1. 有一个名为 “weather” 的 MCP 服务器
  2. 通过运行 uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py 来启动它
保存文件,并重启 Claude for Desktop

通过命令测试

让我们确认 Claude for Desktop 已经识别到我们在 weather 服务器中暴露的两个工具。你可以通过寻找 “Search and tools” 图标来验证:
点击滑块图标后,你应该能看到列出的两个工具:
如果服务器未被 Claude for Desktop 识别,请前往 故障排除 部分获取调试建议。 如果工具设置图标已出现,你现在可以在 Claude for Desktop 中运行以下命令来测试服务器:
  • 萨克拉门托的天气如何?
  • 德克萨斯州有哪些活跃的天气警报?
由于这是美国国家气象局的数据,查询仅适用于美国地区。

背后发生了什么

当你提出问题时:
  1. 客户端将问题发送给 Claude
  2. Claude 分析可用工具并决定使用哪一个或多个
  3. 客户端通过 MCP 服务器执行所选工具
  4. 结果返回给 Claude
  5. Claude 生成自然语言回复
  6. 回复展示给你!

故障排除

从 Claude for Desktop 获取日志与 MCP 相关的 Claude.app 日志写入 ~/Library/Logs/Claude 目录下的日志文件中:
  • mcp.log 包含 MCP 连接及连接失败的常规日志。
  • 名为 mcp-server-SERVERNAME.log 的文件包含来自指定服务器的错误(stderr)日志。
你可以运行以下命令列出最近的日志并实时跟踪新的日志:
# 检查 Claude 的日志是否有错误
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
服务器未在 Claude 中显示
  1. 检查 claude_desktop_config.json 文件的语法
  2. 确保项目路径是绝对路径,而非相对路径
  3. 完全重启 Claude for Desktop
工具调用静默失败如果 Claude 尝试使用工具但失败:
  1. 查看 Claude 的日志以获取错误信息
  2. 验证服务器能否无错误地构建和运行
  3. 尝试重启 Claude for Desktop
以上方法都不奏效,我该怎么办?请参考我们的调试指南,获取更强大的调试工具和更详细的指导。
错误:无法获取网格点数据这通常意味着:
  1. 坐标位于美国之外
  2. NWS API 出现问题
  3. 你被限速了
解决方法:
  • 确认你使用的是美国坐标
  • 在请求之间加入短暂延迟
  • 查看 NWS API 状态页面
错误:[州名] 无活跃警报这不是错误——只是该州当前没有天气警报。尝试其他州,或在恶劣天气时再检查。
如需更高级的故障排查,请查看我们的 MCP 调试指南

下一步

构建客户端

学习如何构建你自己的 MCP 客户端,连接到你的服务器

示例服务器

查看我们官方 MCP 服务器和实现的展示

调试指南

学习如何高效调试 MCP 服务器与集成

使用 LLM 构建 MCP

学习如何使用 Claude 等 LLM 加速你的 MCP 开发