Skip to main content
MCP Server架构示意图:展示Claude Code、MCP Server和外部API三层架构的交互流程

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步流程 如上图所示,从用户提问到返回结果,经历了 6 个步骤:
  1. 用户提问:“北京天气怎么样?”
  2. Claude 理解:识别需要调用天气查询工具
  3. 调用 MCP Server:执行 query_weather("北京")
  4. 请求高德 API:先获取地理编码,再获取天气数据
  5. 数据返回:天气信息返回给 MCP Server
  6. 展示结果:Claude 整理数据并展示给用户

🛠️ 准备工作(10分钟)

1. 安装 Python 3.13+

检查你的 Python 版本:
python3 --version
如果版本低于 3.13,请前往 Python 官网 下载最新版本。

2. 安装 uv 包管理器

uv 是一个超快的 Python 包管理器,比 pip 快 10-100 倍。
# 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. 访问 高德开放平台
  2. 注册账号并登录
  3. 进入控制台应用管理创建新应用
  4. 添加 Key,选择 Web服务
  5. 复制生成的 Key(后面会用到)
API 文档:

4. 安装 Claude Code

Claude Code 是 Anthropic 官方的 CLI 工具,安装方法:
# 使用 npm 安装
npm install -g @anthropic-ai/claude-code

# 或使用 brew(macOS)
brew install claude-code
安装后登录你的 Claude 账号:
claude login

当然也可以使用中转,这里有一个中转站收集的站点:https://awesome-cc.com/ 里面有各种中转站,可以自行选择。 或者选择国产的模型:GLM-4.6或者 MiniMax-M2不仅便宜而且在代码上也是非常好用的

💻 核心开发步骤

第一步:创建项目骨架

打开终端,创建项目:
# 使用 uv 初始化项目
uv init weather-mcp-server
cd weather-mcp-server

# 添加依赖
uv add "mcp[cli]" httpx python-dotenv
项目结构:
weather-mcp-server/
├── main.py              # 主程序
├── pyproject.toml       # 项目配置
├── .env                 # 环境变量(敏感信息)
├── .env.example         # 环境变量模板
├── .gitignore           # Git 忽略文件
└── README.md           # 项目说明

第二步:配置环境变量(安全第一!)

为什么要使用环境变量? 环境变量安全性对比图:展示硬编码API Key与环境变量方式的优缺点对比 如上图所示,硬编码 API Key 会导致:
  • ❌ API Key 被提交到 Git 仓库
  • ❌ 如果推送到 GitHub,Key 会公开暴露
  • ❌ 任何人都能看到并滥用你的 Key
使用环境变量 则可以:
  • ✅ Key 保存在本地 .env 文件
  • .env 文件被 Git 忽略,不会上传
  • ✅ 即使代码公开,Key 也是安全的
操作步骤:
  1. 创建 .env.example 文件(上传到 Git,作为模板):
# 高德地图 API 配置
AMAP_KEY=your_api_key_here
AMAP_HOST=https://restapi.amap.com
  1. 创建 .env 文件(不上传 Git,包含真实 Key):
# 高德地图 API 配置
AMAP_KEY=0fb72bcad*********739221bf  # 替换成你的 Key
AMAP_HOST=https://restapi.amap.com
  1. .gitignore 中添加
.env

第三步:编写核心代码

创建 main.py 文件,写入以下代码:
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 命令:
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
配置内容: 编辑配置文件,添加以下内容:
{
  "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 的客户端的配置信息
uv --directory 你得mcp项目路径 run main.py
运行之后你会得到一个类似:http://0.0.0.0:8080/sse的链接 有的时候根据你对应的代码,可能还会在 sse后面添加一些参数
{
  "mcpServers": {
    "weather": {
      "url": "http://127.0.0.1:8080/sse"
    }
  }
}

第六步:实际使用

启动 Claude Code 并测试:
# 启动 Claude Code
claude

# 验证 mcp 是否加载成功
/mcp
示例对话:
你: 北京今天天气怎么样?

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

[调用 query_weather 工具]

根据查询结果,北京今天多云,气温 15-25℃,东南风 3-4级,
空气质量良好。建议穿着轻薄外套,适合外出活动。
再试试其他城市:
你: 上海呢?

Claude: [调用 query_weather 工具]
上海今天小雨,气温 18-22℃,请记得带伞哦!
恭喜你! 🎉 你的第一个 MCP Server 已经成功运行了!

🚀 进阶优化

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

1. 格式化天气数据

目前返回的是原始 JSON,可以解析后返回更友好的格式:
# 解析天气数据
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. 添加错误处理

if not KEY:
    return [TextContent(
        type="text",
        text="错误:未配置 AMAP_KEY,请检查 .env 文件"
    )]

3. 添加日志记录

import logging

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

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

4. 支持多城市批量查询

@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 文件是否存在且配置正确
  • ✅ 配置文件路径是否正确
调试方法:
# 直接运行看错误信息
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 让更多人学习

📚 参考资源

社交媒体分享卡片图:展示文章封面和标题的视觉设计