面向服务器开发者

在本教程中,我们将构建一个简单的 MCP 天气服务器,并将其连接到主机 Claude for Desktop。我们将从基本设置开始,然后逐步处理更复杂的用例。

我们将要构建的内容

许多大型语言模型(LLM)目前无法获取天气预报和严重天气警报。让我们使用 MCP 来解决这个问题!

我们将构建一个暴露两个工具的服务器:get-alertsget-forecast。然后,我们将把该服务器连接到一个 MCP 主机(在本例中为 Claude for Desktop):

服务器可以连接到任何客户端。我们在此选择 Claude for Desktop 是为了简单起见,但我们也有关于构建您自己的客户端以及其他客户端列表的指南。

核心 MCP 概念

MCP 服务器可以提供三种主要能力:

  1. 资源:客户端可以读取的类似文件的数据(如 API 响应或文件内容)
  2. 工具:LLM 可以调用的函数(需用户批准)
  3. 提示:帮助用户完成特定任务的预写模板

本教程将主要聚焦于工具。

让我们开始构建我们的天气服务器!您可以在此处找到我们将要构建的完整代码。

前置知识

本快速入门假设您熟悉:

  • Python
  • 像 Claude 这样的大型语言模型

系统要求

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

设置您的环境

首先,让我们安装 uv 并设置我们的 Python 项目和环境:

curl -LsSf https://astral.sh/uv/install.sh | sh
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

安装完成后,请重启终端以确保 uv 命令被正确识别。

现在,让我们创建并设置我们的项目:

# 创建项目目录
uv init weather
cd weather

# 创建虚拟环境并激活
uv venv
source .venv/bin/activate

# 安装依赖
uv add "mcp[cli]" httpx

# 创建服务器文件
touch weather.py
# 创建项目目录
uv init weather
cd weather

# 创建虚拟环境并激活
uv venv
.venv\Scripts\activate

# 安装依赖
uv add mcp[cli] httpx

# 创建服务器文件
new-item 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:
    """获取美国某个州的天气警报。

    参数:
        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: 位置的经度
    """
    # 首先获取预报网格端点
    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 以确认一切正常。

现在让我们使用现有的 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 键中添加您的服务器。如果至少有一个服务器正确配置,Claude for Desktop 中才会显示 MCP UI 元素。

在本例中,我们将添加我们的单个天气服务器,如下所示:

{
    "mcpServers": {
        "weather": {
            "command": "uv",
            "args": [
                "--directory",
                "/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
                "run",
                "weather.py"
            ]
        }
    }
}

您可能需要在 command 字段中放入 uv 可执行文件的完整路径。您可以通过在 MacOS/Linux 上运行 which uv 或在 Windows 上运行 where uv 来获取此路径。

确保传入服务器的绝对路径。

这告诉 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 服务器中暴露的两个工具。您可以通过寻找锤子 图标来确认:

点击锤子图标后,您应该看到列出的两个工具:

如果 Claude for Desktop 未识别您的服务器,请继续阅读故障排除部分以获取调试提示。

如果锤子图标已出现,您现在可以通过在 Claude for Desktop 中运行以下命令测试您的服务器:

  • 萨克拉门托的天气如何?
  • 德克萨斯州有哪些活跃的天气警报?

由于这是美国国家气象服务,查询仅适用于美国位置。

幕后发生了什么

当您提出问题时:

  1. 客户端将您的问题发送给 Claude
  2. Claude 分析可用工具并决定使用哪个(或哪些)
  3. 客户端通过 MCP 服务器执行所选工具
  4. 结果被发送回 Claude
  5. Claude 形成自然语言响应
  6. 响应显示给您!

故障排除

有关更高级的故障排除,请查看我们的MCP 调试指南

下一步