本文将手把手教你如何使用 MCP(Model Context Protocol) 开发一个可以实时查询天气信息的插件(tool),并在 Cursor 客户端中直接调用它。


一、准备环境

1. 安装 uv

uv 是一个高效的 Python 环境和包管理工具,比传统的 pip + venv 更轻便实用。
安装命令如下:

curl -LsSf https://astral.sh/uv/install.sh | sh

如果你已经安装过 uv,可以直接跳过这一步。


2. 创建工作区

我在本地创建了一个名为 MCP_Tools 的项目,并在其中新建了一个文件:weather.py
然后使用 uv 进行初始化:

uv init

初始化后,项目目录结构如下图所示:
在这里插入图片描述


📁 二、项目文件结构说明

文件 说明
pyproject.toml 项目配置文件(包含依赖、Python 版本等)
python-version 指定项目 Python 版本(例如 3.12)
.gitignore Git 忽略规则(虚拟环境、缓存、构建产物等)
README.md 项目说明文档

示例:

[project]
name = "mcp-tools"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []

🪄 三、创建虚拟环境

使用 uv 创建虚拟环境:

uv venv
source .venv/bin/activate

执行后会生成 .venv 文件夹,并自动根据 python-version 中的版本创建虚拟环境。
激活后,终端提示符会显示虚拟环境名称。
在这里插入图片描述


四、安装依赖

接下来安装开发 MCP 所需的依赖包:

uv add "mcp[cli]" httpx
  • mcp[cli]:MCP SDK + 命令行工具
  • httpx:轻量级异步 HTTP 客户端

执行完成后,可以看到 pyproject.tomldependencies 列表中自动增加了依赖项:
在这里插入图片描述

其他人只需在项目目录中运行 uv sync 即可同步相同的依赖环境。


五、开发第一个 MCP 工具:实时天气查询

我们将实现一个名为 weather 的 MCP 工具,它支持:

  • 获取美国各州天气预警
  • 查询指定经纬度的天气预报
  • 查询中国城市的实时天气与未来预报(使用高德 API)

1. 初始化 MCP 服务

from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP

# 初始化 FastMCP server
mcp = FastMCP("weather")

NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
GAODE_API_KEY = ""  # 请替换为你自己的高德Key
GAODE_API_BASE = "https://restapi.amap.com/v3/weather/weatherInfo"

2. 定义通用请求函数

# NWS(美国国家气象局)API 请求
async def make_nws_request(url: str) -> dict[str, Any] | None:
    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


# 高德天气 API 请求
async def make_gaode_request(city: str, extensions: str = "base") -> dict[str, Any] | None:
    params = {"city": city, "key": GAODE_API_KEY, "extensions": extensions}
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(GAODE_API_BASE, params=params, timeout=30.0)
            response.raise_for_status()
            return response.json()
        except Exception:
            return None

3. 定义工具方法(Tool Functions)

每个 MCP 工具都由三部分组成:

  1. @mcp.tool() 装饰器
  2. 方法本体
  3. 注释文档(Docstring)
获取美国州级天气预警
@mcp.tool()
async def get_alerts(state: str) -> str:
    """Get weather alerts for a US state."""
    url = f"{NWS_API_BASE}/alerts/active/area/{state}"
    data = await make_nws_request(url)
    if not data or "features" not in data:
        return "Unable to fetch alerts or no alerts found."
    if not data["features"]:
        return "No active alerts for this state."
    alerts = [
        f"Event: {f['properties']['event']}\nArea: {f['properties']['areaDesc']}"
        for f in data["features"]
    ]
    return "\n---\n".join(alerts)
获取指定经纬度天气预报(美国)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    """Get weather forecast for a location."""
    points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
    points_data = await make_nws_request(points_url)
    if not points_data:
        return "Unable to fetch forecast data."
    forecast_url = points_data["properties"]["forecast"]
    forecast_data = await make_nws_request(forecast_url)
    if not forecast_data:
        return "Unable to fetch detailed forecast."
    periods = forecast_data["properties"]["periods"]
    forecasts = [
        f"{p['name']}: {p['temperature']}°{p['temperatureUnit']}, {p['detailedForecast']}"
        for p in periods[:5]
    ]
    return "\n---\n".join(forecasts)
获取中国城市实时天气(高德)
@mcp.tool()
async def get_china_weather(city: str) -> str:
    """获取中国城市当前天气(高德API)"""
    data = await make_gaode_request(city)
    if not data or data.get("status") != "1" or not data.get("lives"):
        return "无法获取该城市的天气信息。"
    live = data["lives"][0]
    return (
        f"{live['city']} 当前天气:\n"
        f"天气:{live['weather']}\n"
        f"温度:{live['temperature']}°C\n"
        f"风向:{live['winddirection']}{live['windpower']}级\n"
        f"湿度:{live['humidity']}%\n"
        f"报告时间:{live['reporttime']}\n"
    )
获取中国城市未来天气预报(高德)
@mcp.tool()
async def get_china_weather_forecast(city: str) -> str:
    """获取中国城市未来天气(高德API)"""
    data = await make_gaode_request(city, extensions="all")
    if not data or data.get("status") != "1" or not data.get("forecasts"):
        return "无法获取该城市的未来天气信息。"
    forecast = data["forecasts"][0]
    city_name = forecast["city"]
    result = [f"{city_name} 未来天气(报告时间:{forecast['reporttime']}):"]
    for day in forecast["casts"]:
        result.append(
            f"{day['date']}(周{day['week']}):白天{day['dayweather']},夜间{day['nightweather']},"
            f"温度{day['daytemp']}~{day['nighttemp']}°C"
        )
    return "\n".join(result)
智能识别天气查询(自动识别中美)
@mcp.tool()
async def get_weather(location: str) -> str:
    """智能查询天气(支持中国城市或经纬度坐标)"""
    if "," in location:
        try:
            lat, lon = map(float, location.split(","))
            return await get_forecast(lat, lon)
        except Exception:
            return "经纬度格式错误,请输入如 '31.23,121.47' 或城市名。"
    return await get_china_weather(location)

六、在 Cursor 中配置 MCP

打开 Cursor 设置 → MCP Servers,添加如下配置:

{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/Users/shushan/Downloads/PycharmProjects/weather",
        "run",
        "weather.py"
      ]
    }
  }
}

配置完成后,MCP 服务名称会显示为绿色,代表连接成功:
在这里插入图片描述


七、开始测试!

在 Cursor 的询问天气状况

成功得到实时的天气信息!

请添加图片描述

这一整套流程不仅适用于天气工具,也可为你后续开发更多 自动化查询类 MCP 插件 打下坚实基础。

参考文档:https://mcp-docs.cn/quickstart/server

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐