> ## Documentation Index
> Fetch the complete documentation index at: https://writer.wjstar.top/llms.txt
> Use this file to discover all available pages before exploring further.

# mcp server 开发

> 30分钟开发你的第一个 MCP Server：让 Claude 实时查询天气

![MCP Server架构示意图：展示Claude Code、MCP Server和外部API三层架构的交互流程](https://virusoss.oss-cn-shanghai.aliyuncs.com/f688836557ddc226d674c93d93f00d6ceabb13b79ee18d6a8567a8456ce1244f.png)

# 30分钟开发你的第一个 MCP Server：让 Claude 实时查询天气

> 从零到一，手把手带你打造一个真实可用的 MCP Server

***

## 🎯 想象这样一个场景

你在终端中启动 Claude Code，输入："北京今天天气怎么样？"

Claude 立刻回复你："北京今天多云，气温 15-25℃，空气质量良好，适合外出。"

**等等！** Claude 不是只能回答它训练数据中的内容吗？它怎么知道**今天**的天气？

答案就是：**MCP Server（Model Context Protocol Server）**。

这篇文章会手把手教你，在 30 分钟内开发一个真实可用的天气查询 MCP Server，让 Claude 拥有获取实时信息的能力。

**本文承诺：**

* ✅ 零基础也能看懂
* ✅ 所有代码都有详细注释
* ✅ 配图说明每个关键概念
* ✅ 最终能在 Claude Code 中实际使用

那么，让我们开始吧！

***

## 📚 什么是 MCP？（3分钟科普）

### MCP 的全称

**MCP = Model Context Protocol（模型上下文协议）**

这是 Anthropic（Claude 的开发公司）推出的一个标准协议，用于让 AI 模型（如 Claude）与外部工具和数据源进行交互。

### 为什么需要 MCP？

Claude 本身是一个**语言模型**，它的能力来自于训练数据。但它有几个天然的局限：

1. **知识截止日期**：训练数据只到某个时间点，无法知道"今天"的信息
2. **无法执行操作**：不能帮你发邮件、操作数据库、调用 API
3. **无法访问私有数据**：不知道你公司的内部文档、客户数据

**MCP 就是为了解决这些问题而生的。**

### MCP 架构一览

MCP 的核心是**三层架构**：

1. **Claude Code**（客户端）：命令行界面，你与 Claude 对话的工具
2. **MCP Server**（中间层）：你开发的程序，负责连接 Claude 和外部服务
3. **外部 API/数据源**：真正提供实时数据的地方（如天气 API、数据库等）

**工作流程：**

* 用户问问题 → Claude 识别需要调用工具 → 调用 MCP Server → MCP Server 调用外部 API → 数据返回 → Claude 整理后展示给用户

### MCP 的核心概念

MCP 主要包含三个核心概念：

1. **Server**：你的 MCP 程序，运行在本地
2. **Tool**：Server 提供的具体功能（如 `query_weather`）
3. **Client**：调用 Server 的应用（如 Claude Code CLI）

理解了这三个概念，你就掌握了 MCP 的精髓。

***

## 🎨 我们要做什么？

### 项目目标

开发一个**天气查询 MCP Server**，实现以下功能：

* 📍 输入任意中国城市名称
* 🌤️ 返回该城市的实时天气信息
* 💬 在 Claude Code CLI 中无缝使用

### 技术选型

* **编程语言**：Python 3.13+
* **MCP 框架**：FastMCP（Anthropic 官方推荐）
* **HTTP 库**：httpx（异步 HTTP 客户端）
* **外部 API**：高德地图天气 API（免费，国内速度快）
* **包管理器**：uv（比 pip 快 10-100 倍）

### 完整流程

![MCP Server工作流程图：展示从用户提问到Claude返回结果的完整6步流程](https://virusoss.oss-cn-shanghai.aliyuncs.com/workflow-diagram.png)

如上图所示，从用户提问到返回结果，经历了 6 个步骤：

1. **用户提问**："北京天气怎么样？"
2. **Claude 理解**：识别需要调用天气查询工具
3. **调用 MCP Server**：执行 `query_weather("北京")`
4. **请求高德 API**：先获取地理编码，再获取天气数据
5. **数据返回**：天气信息返回给 MCP Server
6. **展示结果**：Claude 整理数据并展示给用户

***

## 🛠️ 准备工作（10分钟）

### 1. 安装 Python 3.13+

检查你的 Python 版本：

```bash theme={null}
python3 --version
```

如果版本低于 3.13，请前往 [Python 官网](https://www.python.org/) 下载最新版本。

### 2. 安装 uv 包管理器

uv 是一个超快的 Python 包管理器，比 pip 快 10-100 倍。

```bash theme={null}
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
```

### 3. 注册高德地图 API Key

1. 访问 [高德开放平台](https://lbs.amap.com/)
2. 注册账号并登录
3. 进入**控制台** → **应用管理** → **创建新应用**
4. 添加 **Key**，选择 **Web服务**
5. 复制生成的 **Key**（后面会用到）

**API 文档：**

* [地理编码 API](https://lbs.amap.com/api/webservice/guide/api/georegeo/)
* [天气查询 API](https://lbs.amap.com/api/webservice/guide/api-advanced/weatherinfo)

### 4. 安装 Claude Code

Claude Code 是 Anthropic 官方的 CLI 工具，安装方法：

```bash theme={null}
# 使用 npm 安装
npm install -g @anthropic-ai/claude-code

# 或使用 brew（macOS）
brew install claude-code
```

安装后登录你的 Claude 账号：

```bash theme={null}
claude login
```

***

当然也可以使用中转，这里有一个中转站收集的站点：[https://awesome-cc.com/](https://awesome-cc.com/) 里面有各种中转站，可以自行选择。

或者选择国产的模型：`GLM-4.6`或者 `MiniMax-M2`不仅便宜而且在代码上也是非常好用的

* GLM Code Plan：[https://www.bigmodel.cn/claude-code?ic=2MS3XWKPCF](https://www.bigmodel.cn/claude-code?ic=2MS3XWKPCF)
* MiniMax-M2 Code Plan：[https://platform.minimaxi.com/subscribe/coding-plan](https://platform.minimaxi.com/subscribe/coding-plan)

## 💻 核心开发步骤

### 第一步：创建项目骨架

打开终端，创建项目：

```bash theme={null}
# 使用 uv 初始化项目
uv init weather-mcp-server
cd weather-mcp-server

# 添加依赖
uv add "mcp[cli]" httpx python-dotenv
```

**项目结构：**

```plain theme={null}
weather-mcp-server/
├── main.py              # 主程序
├── pyproject.toml       # 项目配置
├── .env                 # 环境变量（敏感信息）
├── .env.example         # 环境变量模板
├── .gitignore           # Git 忽略文件
└── README.md           # 项目说明
```

***

### 第二步：配置环境变量（安全第一！）

**为什么要使用环境变量？**

![环境变量安全性对比图：展示硬编码API Key与环境变量方式的优缺点对比](https://virusoss.oss-cn-shanghai.aliyuncs.com/env-security-comparison.png)

如上图所示，**硬编码 API Key** 会导致：

* ❌ API Key 被提交到 Git 仓库
* ❌ 如果推送到 GitHub，Key 会公开暴露
* ❌ 任何人都能看到并滥用你的 Key

**使用环境变量** 则可以：

* ✅ Key 保存在本地 `.env` 文件
* ✅ `.env` 文件被 Git 忽略，不会上传
* ✅ 即使代码公开，Key 也是安全的

**操作步骤：**

1. **创建 **`.env.example`** 文件**（上传到 Git，作为模板）：

```plain theme={null}
# 高德地图 API 配置
AMAP_KEY=your_api_key_here
AMAP_HOST=https://restapi.amap.com
```

2. **创建 **`.env`** 文件**（不上传 Git，包含真实 Key）：

```plain theme={null}
# 高德地图 API 配置
AMAP_KEY=0fb72bcad*********739221bf  # 替换成你的 Key
AMAP_HOST=https://restapi.amap.com
```

3. **在 **`.gitignore`** 中添加**：

```plain theme={null}
.env
```

***

### 第三步：编写核心代码

创建 `main.py` 文件，写入以下代码：

```python theme={null}
import json
import os
import httpx
from mcp.server import FastMCP
from mcp.types import TextContent
from dotenv import load_dotenv

# 加载 .env 文件中的环境变量
load_dotenv()

# 创建 FastMCP 应用实例
app = FastMCP("weather-mcp-server")

# 从环境变量读取配置
HOST = os.getenv("AMAP_HOST", "https://restapi.amap.com")
KEY = os.getenv("AMAP_KEY")


# 定义工具：查询天气
@app.tool(
    name="query_weather",
    description="查询指定地区的天气情况"
)
async def query_weather(address: str) -> list[TextContent]:
    """
    查询指定地区的天气

    Args:
        address: 地区名称，如 "北京"、"上海"

    Returns:
        天气信息列表
    """
    async with httpx.AsyncClient() as client:
        try:
            # 步骤1: 通过地址获取地理编码（adcode）
            resp = await client.get(
                f"{HOST}/v3/geocode/geo",
                params={"key": KEY, "address": address}
            )

            if resp.status_code != 200:
                return [TextContent(
                    type="text",
                    text=f"请求失败: {resp.status_code}"
                )]

            resp_dict = json.loads(resp.text)

            # 注意：高德 API 的 status 是字符串 "1"
            if resp_dict["status"] != "1":
                return [TextContent(
                    type="text",
                    text=f"地理编码失败: {resp_dict['info']}"
                )]

            # 获取城市代码
            city = resp_dict["geocodes"][0]["adcode"]

            # 步骤2: 通过城市代码查询天气
            resp = await client.get(
                f"{HOST}/v3/weather/weatherInfo",
                params={"key": KEY, "city": city}
            )

            if resp.status_code != 200:
                return [TextContent(
                    type="text",
                    text=f"天气查询失败: {resp.status_code}"
                )]

            resp_dict = json.loads(resp.text)

            if resp_dict["status"] != "1":
                return [TextContent(
                    type="text",
                    text=f"天气查询失败: {resp_dict['info']}"
                )]

            # 返回天气数据
            return [TextContent(type="text", text=resp.text)]

        except Exception as e:
            return [TextContent(
                type="text",
                text=f"发生错误: {str(e)}"
            )]


# 程序入口
if __name__ == "__main__":
    # 以 stdio 模式运行（Claude Code CLI 需要）
    # 这里也能换成 sse 那么对应的 mcp 的配置也需要进行调整
    app.run(transport="stdio")
```

**代码关键点解析：**

1. `load_dotenv()`：加载 `.env` 文件中的环境变量
2. `FastMCP("weather-mcp-server")`：创建 MCP Server 实例
3. `@app.tool(...)`：装饰器，将函数注册为 MCP 工具
4. `async def query_weather(...)`：异步函数，调用外部 API
5. `app.run(transport="stdio")`：以标准输入输出模式运行（Claude Code CLI 通过 stdio 与 MCP Server 通信）

**高德 API 调用流程：**

1. **地理编码**：`address`（如"北京"） → `adcode`（城市代码）
2. **天气查询**：`adcode` → 天气数据

***

### 第四步：本地测试

在开发过程中，我们需要测试 MCP Server 是否正常工作。

**使用 **`mcp dev`** 命令：**

```bash theme={null}
mcp dev main.py
```

运行后，会自动打开一个 Web 页面，你可以在上面：

* 查看 MCP Server 提供的工具
* 测试 `query_weather` 功能
* 查看返回的数据

**测试示例：**

* 输入：`{"address": "北京"}`
* 预期输出：包含北京天气信息的 JSON 数据

***

### 第五步：集成到 Claude Code

测试通过后，我们需要将 MCP Server 集成到 Claude Code。

**配置文件位置：**

* **macOS/Linux**: `~/.claude.json`
* **Windows**: `%USERPROFILE%\.claude.json`（或 `C:\Users\你的用户名\.claude.json`）

**配置内容：**

编辑配置文件，添加以下内容：

```json theme={null}
{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/你的项目路径/weather-mcp-server",
        "run",
        "main.py"
      ]
    }
  }
}
```

**重要提示：**

* 将 `/你的项目路径/weather-mcp-server` 替换为你实际的项目路径
* macOS 示例：`/Users/yourname/projects/weather-mcp-server`
* Windows 示例：`C:\\Users\\yourname\\projects\\weather-mcp-server`

**重新加载配置**

保存配置文件后，重启 Claude Code CLI 或重新运行即可生效。

**如果transport="sse"改成这样之后，则需要在终端进行手动运行，然后重新配置 claude或者其他的可以连接 mcp 的客户端的配置信息**

```bash theme={null}
uv --directory 你得mcp项目路径 run main.py
```

运行之后你会得到一个类似：`http://0.0.0.0:8080/sse`的链接

有的时候根据你对应的代码，可能还会在 `sse`后面添加一些参数

```json theme={null}
{
  "mcpServers": {
    "weather": {
      "url": "http://127.0.0.1:8080/sse"
    }
  }
}
```

***

### 第六步：实际使用

启动 Claude Code 并测试：

```bash theme={null}
# 启动 Claude Code
claude

# 验证 mcp 是否加载成功
/mcp
```

**示例对话：**

```plain theme={null}
你: 北京今天天气怎么样？

Claude: 让我帮你查询北京的天气。

[调用 query_weather 工具]

根据查询结果，北京今天多云，气温 15-25℃，东南风 3-4级，
空气质量良好。建议穿着轻薄外套，适合外出活动。
```

**再试试其他城市：**

```plain theme={null}
你: 上海呢？

Claude: [调用 query_weather 工具]
上海今天小雨，气温 18-22℃，请记得带伞哦！
```

**恭喜你！** 🎉 你的第一个 MCP Server 已经成功运行了！

***

## 🚀 进阶优化

如果你想让 MCP Server 更强大，可以尝试以下优化：

### 1. 格式化天气数据

目前返回的是原始 JSON，可以解析后返回更友好的格式：

```python theme={null}
# 解析天气数据
weather_data = resp_dict["lives"][0]
formatted_text = f"""
城市：{weather_data['province']} {weather_data['city']}
天气：{weather_data['weather']}
温度：{weather_data['temperature']}℃
风向：{weather_data['winddirection']}风
风力：{weather_data['windpower']}级
湿度：{weather_data['humidity']}%
更新时间：{weather_data['reporttime']}
"""

return [TextContent(type="text", text=formatted_text)]
```

### 2. 添加错误处理

```python theme={null}
if not KEY:
    return [TextContent(
        type="text",
        text="错误：未配置 AMAP_KEY，请检查 .env 文件"
    )]
```

### 3. 添加日志记录

```python theme={null}
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

logger.info(f"查询天气: {address}")
```

### 4. 支持多城市批量查询

```python theme={null}
@app.tool(name="query_weather_batch")
async def query_weather_batch(cities: list[str]):
    """批量查询多个城市的天气"""
    results = []
    for city in cities:
        # ... 查询逻辑
        results.append(weather_info)
    return results
```

***

## 🙋 常见问题 FAQ

### Q1: MCP Server 启动失败怎么办？

**检查清单：**

* ✅ Python 版本是否 >= 3.13
* ✅ 依赖是否正确安装（`uv sync`）
* ✅ `.env` 文件是否存在且配置正确
* ✅ 配置文件路径是否正确

**调试方法：**

```bash theme={null}
# 直接运行看错误信息
uv run python main.py
```

### Q2: Claude Code 找不到工具？

**可能原因：**

* `.claude.json` 配置文件格式错误
* 配置文件路径不正确
* MCP Server 启动失败

**解决方法：**

1. 检查 `.claude.json` 配置文件格式是否正确
2. 确认项目路径是绝对路径
3. 尝试直接运行 MCP Server 查看错误信息：`uv run python main.py`
4. 检查 Claude Code 的输出日志

### Q3: API Key 无效？

**检查步骤：**

1. 确认 Key 已在高德平台生成
2. 确认 Key 类型是 **Web服务**
3. 确认 `.env` 文件中 Key 正确无误
4. 尝试直接访问 API 测试

### Q4: 返回数据格式不对？

**高德 API 注意事项：**

* `status` 字段是字符串 `"1"` 而非数字 `1`
* 需要先调用地理编码 API 获取 `adcode`
* 天气数据在 `lives` 数组中

### Q5: 能查询国外城市吗？

高德地图 API 主要支持中国城市。如需查询国外城市，可以：

* 使用 OpenWeatherMap API
* 使用 WeatherAPI
* 使用 AccuWeather API

***

## 📝 总结

恭喜你完成了第一个 MCP Server 的开发！让我们回顾一下学到的内容：

### 核心知识点

1. **MCP 架构**：Client ↔ Server ↔ External API
2. **环境变量管理**：保护敏感信息的正确姿势
3. **FastMCP 框架**：快速搭建 MCP Server
4. **异步编程**：使用 `async/await` 调用外部 API
5. **Claude Code CLI 集成**：通过 `.claude.json` 配置 MCP Server

### MCP 的更多可能性

MCP Server 不仅可以查询天气，还可以实现：

* 📧 **发送邮件**：集成 SMTP 服务
* 📊 **数据库查询**：连接 MySQL、PostgreSQL
* 📁 **文件操作**：读写本地文件
* 🌐 **网页抓取**：获取网页内容
* 🤖 **自动化任务**：执行系统命令
* 🔐 **私有数据访问**：查询公司内部系统

**天空才是极限！** ✨

### 下一步行动

1. **优化代码**：添加更多错误处理和日志
2. **扩展功能**：支持更多天气查询参数
3. **开发新 Server**：尝试其他类型的 MCP Server
4. **分享经验**：写博客、发 GitHub 让更多人学习

***

## 📚 参考资源

* [MCP 官方文档](https://modelcontextprotocol.io/)
* [FastMCP GitHub](https://github.com/jlowin/fastmcp)
* [高德地图 API 文档](https://lbs.amap.com/api/webservice/summary)
* [本项目 GitHub](https://github.com/sword-demon/weather-mcp-server)

![社交媒体分享卡片图：展示文章封面和标题的视觉设计](https://virusoss.oss-cn-shanghai.aliyuncs.com/social-card.png)
