# 如何构建你的第一个MCP服务器：分步教程

学习从零开始构建模型上下文协议（MCP）服务器。这个实用教程将教你如何为Claude等AI助手创建访问外部API的工具。

Canonical URL: https://a2a-mcp.org/blog/how-to-build-mcp-server-zh

Language: zh

Published: 2026-04-06

Updated: 2026-04-06

## 环境准备

开始之前，请确保已准备好以下内容：

- 已安装 **Python 3.10 或更高版本**。
- 基本熟悉 Python 函数和异步代码。
- [uv](https://docs.astral.sh/uv/getting-started/installation/)（快速的 Python 包管理器） – 通过 `curl -LsSf https://astral.sh/uv/install.sh | sh` 安装。
- 一个 MCP 客户端，例如 **Claude Desktop**（从 claude.ai/download 下载并保持更新）。
- 一个文本编辑器或 IDE。

无需事先具备 MCP 经验。我们将构建一个实用的 **天气 MCP 服务器**，让 AI 能够通过国家气象局 API 查询美国实时天气警报和预报。

## 步骤 1：设置环境

创建一个干净的项目目录，并使用 uv 初始化它：

```bash
mkdir weather-mcp-server
cd weather-mcp-server
uv init
uv venv
source .venv/bin/activate  # Windows 系统: .venv\Scripts\activate
uv add "mcp[cli]" httpx
```

这将安装官方的 MCP Python SDK (FastMCP) 和用于 API 调用的 httpx。你的项目现在拥有 `pyproject.toml` 文件和虚拟环境。

**预期输出：** 一个新的 `.venv` 文件夹，以及依赖项列在 `uv.lock` 中。

## 步骤 2：创建 MCP 服务器代码

创建主文件：

```bash
touch weather.py
```

将这段完整且可直接运行的代码粘贴到 `weather.py` 中：

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

# 初始化 MCP 服务器
mcp = FastMCP("weather")

NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"

# 安全调用 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

# 为 AI 友好地格式化天气警报
def format_alert(feature: dict) -> str:
    props = feature["properties"]
    return f"""
事件: {props.get("event", "Unknown")}
地区: {props.get("areaDesc", "Unknown")}
严重程度: {props.get("severity", "Unknown")}
描述: {props.get("description", "No description available")}
应对指南: {props.get("instruction", "No specific instructions provided")}
"""

# 工具 1：获取美国某个州的活跃天气警报
@mcp.tool()
async def get_alerts(state: str) -> str:
    """获取美国某个州（例如 "CA" 或 "TX"）的当前天气警报。"""
    url = f"{NWS_API_BASE}/alerts/active/area/{state.upper()}"
    data = await make_nws_request(url)
    if not data or "features" not in data:
        return "无法获取警报或未找到警报。"
    if not data["features"]:
        return f"{state.upper()} 没有活跃警报。"
    alerts = [format_alert(f) for f in data["features"]]
    return "\n---\n".join(alerts)
```

# 工具 2：获取任意经纬度的 5 天预报
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    """获取特定经纬度的天气预报。"""
    points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
    points_data = await make_nws_request(points_url)
    if not points_data:
        return "无法获取此位置的预报数据。"
    forecast_url = points_data["properties"]["forecast"]
    forecast_data = await make_nws_request(forecast_url)
    if not forecast_data:
        return "无法获取详细预报。"
    periods = forecast_data["properties"]["periods"][:5]
    forecasts = []
    for period in periods:
        forecast = f"""
{period["name"]}:
温度: {period["temperature"]}°{period["temperatureUnit"]}
风速: {period["windSpeed"]} {period["windDirection"]}
预报: {period["detailedForecast"]}
"""
        forecasts.append(forecast)
    return "\n---\n".join(forecasts)

def main():
    mcp.run(transport="stdio")

if __name__ == "__main__":
    main()
```

**关键概念解释：**
- `@mcp.tool()` 装饰器将普通的异步函数转换为 AI 可发现和调用的 MCP 工具。
- 服务器通过 **stdio**（标准输入/输出）运行——这是本地 MCP 服务器的默认设置。
- 所有日志都应输出到 stderr（FastMCP 会自动处理）。

## 步骤 3：本地测试服务器

运行服务器：

```bash
uv run weather.py
```

**预期输出：**
终端保持打开且静默（这是 stdio 服务器的正常现象）。只有当 MCP 客户端连接时，你才会看到 JSON-RPC 消息。

保持此终端运行以进行下一步。

## 步骤 4：将 MCP 服务器连接到 Claude Desktop

1. 打开 Claude Desktop。
2. 在以下路径创建或编辑配置文件：
   - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

添加以下确切条目（将 `/ABSOLUTE/PATH/TO/weather-mcp-server` 替换为你的实际文件夹路径）：

```json
{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/ABSOLUTE/PATH/TO/weather-mcp-server",
        "run",
        "weather.py"
      ]
    }
  }
}
```

3. 完全退出 Claude Desktop（macOS 按 Cmd+Q，Windows 从系统托盘关闭）并重新启动。
4. 在 Claude 中，点击 **“添加文件、连接器等”** → 将鼠标悬停在 **Connectors** 上 → 你应该能看到列表中的 **“weather”**。

## 步骤 5：在 AI 中使用你的 MCP 服务器

在 Claude Desktop 中尝试以下提示：

- “德克萨斯州有哪些活跃的天气警报？”
- “给我旧金山的预报（使用纬度 37.77，经度 -122.41）。”
- “检查加利福尼亚州的警报，并告诉我是否需要准备应对任何情况。”

Claude 将自动发现工具，首次使用时会请求你的批准，并返回格式化的结果。

**预期行为：** AI 会在后台调用你的工具，并以自然语言的形式显示答案。

## 常见问题与故障排除

- **服务器未在 Claude 中显示**：
  - 仔细检查 JSON 格式是否有效（无尾部逗号）。
  - 在配置中使用**绝对路径**。
  - 完全重启 Claude。
  - 检查日志：`~/Library/Logs/Claude/mcp*.log`（macOS）或 Windows 中的等效路径。

- **API 错误或无数据**：
  - NWS API 仅适用于美国地区。
  - 使用两个字母的州代码（如 CA、TX 等）。
  - 坐标必须是有效的经纬度。

- **“命令未找到”**：
  - 确保 uv 已在 PATH 环境变量中，且虚拟环境已激活。
  - 运行 `uv --version` 以验证安装。

- **超时或响应缓慢**：
  - 如有需要，可在 `make_nws_request` 中增加超时设置。
  - NWS 有速率限制——在生产环境中避免频繁请求。

- **权限问题**：
  - 在 macOS 上，前往“系统设置”→“隐私与安全性”，授予 Claude Desktop 完全磁盘访问权限。

## 后续步骤

- **添加更多工具**：使用相同的 `@mcp.tool()` 模式，为数据库、GitHub、Slack 或您自己的 API 创建工具。
- **添加资源和提示**：使用 `mcp.resource()` 和 `mcp.prompt()` 提供文件类数据和可重用的指令。
- **远程部署**：切换到 HTTP/SSE 传输协议，并在 AWS Lambda、Vercel 或任意服务器上托管（FastMCP 支持 `stateless_http=True`）。
- **支持多语言**：尝试使用官方的 TypeScript、Go 或 Rust SDK 以实现相同功能。
- **分享您的服务器**：发布代码仓库，以便他人可通过 `npx` 或 Docker 添加使用。

现在，您已拥有一个功能完整的 MCP 服务器，任何兼容的 AI 客户端均可使用。开始实验、扩展工具，即刻构建强大的 AI 集成方案吧！
