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

环境准备
开始之前,请确保已准备好以下内容:
- 已安装 Python 3.10 或更高版本。
- 基本熟悉 Python 函数和异步代码。
- uv(快速的 Python 包管理器) – 通过
curl -LsSf https://astral.sh/uv/install.sh | sh安装。 - 一个 MCP 客户端,例如 Claude Desktop(从 claude.ai/download 下载并保持更新)。
- 一个文本编辑器或 IDE。
无需事先具备 MCP 经验。我们将构建一个实用的 天气 MCP 服务器,让 AI 能够通过国家气象局 API 查询美国实时天气警报和预报。
步骤 1:设置环境
创建一个干净的项目目录,并使用 uv 初始化它:
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 服务器代码
创建主文件:
touch weather.py
将这段完整且可直接运行的代码粘贴到 weather.py 中:
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
- 打开 Claude Desktop。
- 在以下路径创建或编辑配置文件:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
添加以下确切条目(将 /ABSOLUTE/PATH/TO/weather-mcp-server 替换为你的实际文件夹路径):
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/weather-mcp-server",
"run",
"weather.py"
]
}
}
}
- 完全退出 Claude Desktop(macOS 按 Cmd+Q,Windows 从系统托盘关闭)并重新启动。
- 在 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 集成方案吧!