Skip to main content
Glama
README.md
# Weather MCP Demo:基于 FastMCP 的天气查询工具

## 项目简介

本项目使用 Python + FastMCP + Open-Meteo API 实现一个本地 MCP Server,让大模型客户端可以调用天气查询工具。

项目通过 Open-Meteo 的 Geocoding API 查询城市经纬度,再通过 Forecast API 查询实时天气。整个过程不需要 API Key,适合本地开发、课程展示和实习面试讲解。

## 项目功能

- 根据城市名查询实时天气
- 根据经纬度查询实时天气
- 支持中文城市名和英文城市名
- 返回温度、体感温度、湿度、天气状态、风速、风向
- 支持本地 MCP Client 测试,无 Claude 额度也能验证

## 技术栈

- Python
- FastMCP
- MCP Python SDK
- Open-Meteo API
- requests
- stdio

## 项目结构

```text
weather-mcp-demo/
├── server.py
├── test_weather.py
├── test_mcp_client.py
├── requirements.txt
└── README.md
```

核心文件说明:

- `server.py`:MCP Server 主程序,使用 FastMCP 暴露天气查询工具
- `test_weather.py`:普通 Python 测试脚本,用来验证 Open-Meteo API 逻辑
- `test_mcp_client.py`:本地 MCP Client 测试脚本,用来模拟客户端调用 MCP 工具
- `requirements.txt`:项目依赖
- `README.md`:项目说明文档

## 运行步骤

进入项目目录:

```bash
cd weather-mcp-demo
```

安装依赖:

```bash
python -m pip install -r requirements.txt
```

先测试普通 API 逻辑:

```bash
python test_weather.py
```

再测试 MCP Client 调用工具:

```bash
python test_mcp_client.py
```

最后可以直接启动 MCP Server:

```bash
python server.py
```

## 重点解释

### test_weather.py 的作用

`test_weather.py` 用来测试普通 API 逻辑。

它不会启动 MCP Server,而是直接导入 `server.py` 中的天气查询函数,验证:

- 城市名能否正确转换为经纬度
- Open-Meteo Forecast API 是否能返回实时天气
- 天气结果是否能格式化成中文报告

这个脚本适合在开发阶段先确认核心业务逻辑是否正常。

### test_mcp_client.py 的作用

`test_mcp_client.py` 用来模拟 MCP 客户端调用工具。

它的意义是:即使没有 Claude 额度,也可以在本地验证 MCP Server 是否真的暴露了工具、工具是否能被客户端调用、返回结果是否正确。

这比只运行 `server.py` 更适合调试和面试演示。

### server.py 的 stdio 模式

`server.py` 使用 stdio 模式运行。

stdio 模式下,MCP Server 通过标准输入和标准输出与 MCP Client 通信。因此单独运行:

```bash
python server.py
```

终端没有普通输出是正常的。它不是卡死,而是在等待 MCP Client 发送协议消息。

## 面试讲解版流程

用户输入城市名 -> Geocoding API 获取经纬度 -> Forecast API 获取实时天气 -> MCP tool 封装结果 -> MCP Client/Claude 调用工具。

可以这样讲:

1. 用户输入城市名,例如“杭州”或 `Tokyo`。
2. MCP Client 或 Claude 调用 `get_weather` 工具。
3. `server.py` 先把中文城市名映射成英文城市名,例如“杭州”映射为 `Hangzhou`。
4. 程序调用 Open-Meteo Geocoding API,把城市名转换成经纬度。
5. 程序调用 Open-Meteo Forecast API,根据经纬度查询实时天气。
6. 程序把温度、体感温度、湿度、天气状态、风速、风向整理成中文报告。
7. MCP tool 把结果返回给 MCP Client 或 Claude。

这个项目展示了一个完整的 MCP 工具调用链路:用户需求、工具调用、外部 API 查询、结果封装、返回给大模型客户端。

## MCP 工具说明

### get_weather

根据城市名查询实时天气。

参数:

- `city`:城市名,例如 `杭州`、`上海`、`Tokyo`
- `country_code`:可选国家代码,例如 `CN`、`JP`

### get_weather_by_location

根据经纬度查询实时天气。

参数:

- `latitude`:纬度
- `longitude`:经度

## Claude Desktop 配置示例

如果要接入 Claude Desktop,可以在 Claude Desktop 的 MCP 配置中加入:

```json
{
  "mcpServers": {
    "weather-mcp-demo": {
      "command": "你的conda环境python.exe绝对路径",
      "args": [
        "你的项目server.py绝对路径"
      ]
    }
  }
}
```

Windows 示例:

```json
{
  "mcpServers": {
    "weather-mcp-demo": {
      "command": "C:\\Users\\你的用户名\\miniconda3\\envs\\weather-mcp-demo\\python.exe",
      "args": [
        "D:\\Proj\\mcp_weather\\weather-mcp-demo\\server.py"
      ]
    }
  }
}
```

注意:JSON 中的 Windows 路径反斜杠需要写成 `\\`。

## 常见问题

### 1. 为什么不用 API Key

因为项目使用的是 Open-Meteo API。

Open-Meteo 提供免费的 Geocoding API 和 Forecast API,基础天气查询不需要注册账号,也不需要 API Key。这样项目更容易本地运行,也更适合面试展示。

### 2. 为什么没有 Claude 额度也能测试

因为 MCP Server 本质上是一个本地工具服务。

除了 Claude Desktop,项目也可以使用本地 MCP Client 脚本调用工具。`test_mcp_client.py` 就是用来模拟 MCP Client 的,所以即使没有 Claude 额度,也可以验证 MCP 工具是否能正常工作。

### 3. 为什么 python server.py 看起来卡住

这是正常现象。

`server.py` 使用 stdio 模式运行,它启动后会等待 MCP Client 通过标准输入发送 MCP 协议消息。单独在终端运行时没有普通输出,看起来像卡住,其实是在等待客户端连接。

### 4. KeyboardInterrupt 是否是报错

如果你在终端运行 `python server.py` 后按下 `Ctrl + C`,可能会看到 `KeyboardInterrupt`。

这不是项目逻辑错误,而是你手动中断了正在等待客户端消息的 MCP Server。调试时可以直接关闭终端,或者按 `Ctrl + C` 停止服务。

## 面试时可以强调的点

- 项目没有使用需要 API Key 的服务,降低了运行门槛
- 支持中文和英文城市名,考虑了中文用户输入场景
- 拆分了普通 API 测试和 MCP Client 测试,方便定位问题
- 使用 FastMCP 暴露工具,代码结构简单,适合讲清楚 MCP 的工作方式
- `server.py` 不使用普通 `print` 输出,避免干扰 stdio 协议通信