MCP Server开发教程
快速开始
面向服务端开发者#
在本教程中,我们将构建一个简单的 MCP 天气服务端,并将其连接到主机 Claude for Desktop。我们将从基本设置开始,然后逐步深入到更复杂的用例。
###
我们将构建什么#
许多 LLM 目前没有获取天气预报和恶劣天气警报的能力。让我们使用 MCP 来解决这个问题!
我们将构建一个暴露两个工具的服务端:get-alerts
和 get-forecast
。然后我们将服务端连接到 MCP 主机(在本例中为 Claude for Desktop):
服务端可以连接到任何客户端。我们在这里选择 Claude for Desktop 是为了简单起见,但我们也有关于构建自己的客户端的指南,以及其他客户端的列表。
为什么选择 Claude for Desktop 而不是 Claude.ai?
因为服务端是本地运行的,MCP 目前只支持桌面主机。远程主机正在积极开发中。
MCP 核心概念#
MCP 服务端可以提供三种主要类型的功能:
- 资源:客户端可以读取的文件类数据(如 API 响应或文件内容)
- 工具:LLM 可以调用的函数(需用户批准)
- 提示:帮助用户完成特定任务的预写模板
本教程将主要关注工具。
Python 教程 (其他语言看这里)#
让我们开始构建我们的天气服务端!你可以在这里找到我们将构建的完整代码。
预备知识#
本快速入门假设你熟悉:
- Python
- 像 Claude 这样的 LLM
系统要求#
- 已安装 Python 3.10 或更高版本。
- 你必须使用 Python MCP SDK 1.2.0 或更高版本。
设置你的环境#
首先,让我们安装 uv
并设置我们的 Python 项目和环境:
Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
确保之后重新启动终端,以确保 uv
命令被识别。
现在,让我们创建并设置我们的项目:
Liunx
# 为我们的项目创建一个新目录
uv init weather
cd weather
# 创建虚拟环境并激活它
uv venv
source .venv/bin/activate
# 安装依赖项
uv add "mcp[cli]" httpx
# 创建我们的服务端文件
touch weather.py
现在让我们深入构建你的服务端。
构建你的服务端#
导入包并设置实例#
将这些添加到 weather.py
的顶部:
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化FastMCP服务端
mcp = FastMCP("weather")
# 常量
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
FastMCP 类使用 Python 类型提示和文档字符串自动生成工具定义,使得创建和维护 MCP 工具变得容易。
辅助函数#
接下来,让我们添加用于查询和格式化来自国家气象局 API 的数据的辅助函数:
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""向NWS API发出请求并进行适当的错误处理。"""
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
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get('event', 'Unknown')}
Area: {props.get('areaDesc', 'Unknown')}
Severity: {props.get('severity', 'Unknown')}
Description: {props.get('description', 'No description available')}
Instructions: {props.get('instruction', 'No specific instructions provided')}
"""
实现工具执行#
工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它:
@mcp.tool()
async def get_alerts(state: str) -> str:
"""获取美国州的天气警报。
参数:
state: 两个字母的美国州代码(例如CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "无法获取警报或未找到警报。"
if not data["features"]:
return "该州没有活跃的警报。"
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""获取某个位置的天气预报。
参数:
latitude: 位置的纬度
longitude: 位置的经度
"""
# 首先获取预测网格端点
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取该位置的预测数据。"
# 从points响应中获取预测URL
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预测。"
# 将时间段格式化为可读的预测
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period['name']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
运行服务端#
最后,让我们初始化并运行服务端:
if __name__ == "__main__":
# 初始化并运行服务端
mcp.run(transport='stdio')
你的服务端完成了!运行 uv run weather.py
以确认一切正常。
现在让我们从现有的 MCP 主机 Claude for Desktop 测试你的服务端。
使用 Claude for Desktop 测试你的服务端#
Claude for Desktop 尚未在 Linux 上提供。Linux 用户可以继续构建客户端教程,以构建一个连接到我们刚刚构建的服务端的 MCP 客户端。
首先,确保你已经安装了 Claude for Desktop。你可以在这里安装最新版本。 如果你已经安装了 Claude for Desktop,请确保它已更新到最新版本。
我们需要为你想使用的任何 MCP 服务端配置 Claude for Desktop。为此,请在文本编辑器中打开你的 Claude for Desktop 应用程序配置 ~/Library/Application Support/Claude/claude_desktop_config.json
。如果文件不存在,请确保创建它。
例如,如果你安装了 VS Code:
Linux
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
然后你将在 mcpServers
键中添加你的服务端。只有在至少正确配置了一个服务端的情况下,MCP UI 元素才会在 Claude for Desktop 中显示。
在这种情况下,我们将添加我们的单个天气服务端,如下所示:
Linux
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
你可能需要在 command
字段中输入 uv
可执行文件的完整路径。你可以通过在 MacOS/Linux 上运行 which uv
或在 Windows 上运行 where uv
来获取此路径。
确保你传入服务端的绝对路径。
这告诉 Claude for Desktop:
- 有一个名为 “weather” 的 MCP 服务端
- 通过运行
uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py
来启动它
保存文件,并重新启动 Claude for Desktop。
这告诉 Claude for Desktop:
- 有一个名为 “weather” 的 MCP 服务端
- 通过运行
java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/libs/weather-0.1.0-all.jar
来启动它
保存文件,并重新启动 Claude for Desktop。
</Tabs.Tab>
使用命令测试#
让我们确保 Claude for Desktop 能够识别我们在 weather
服务端中暴露的两个工具。你可以通过查找锤子图标来做到这一点:
点击锤子图标后,你应该看到列出的两个工具:
如果你的服务端没有被 Claude for Desktop 识别,请继续故障排除部分以获取调试提示。
如果锤子图标已经显示,你现在可以通过在 Claude for Desktop 中运行以下命令来测试你的服务端:
- 萨克拉门托的天气如何?
- 德克萨斯州有哪些活跃的天气警报?
由于这是美国国家气象局服务,查询仅适用于美国位置。
幕后发生了什么#
当你提出问题时:
- 客户端将你的问题发送给 Claude
- Claude 分析可用的工具并决定使用哪个工具
- 客户端通过 MCP 服务端执行所选工具
- 结果被发送回 Claude
- Claude 制定自然语言响应
- 响应显示给你!
故障排除#
Claude for Desktop 集成问题
从 Claude for Desktop 获取日志
与 MCP 相关的 Claude.app 日志写入 ~/Library/Logs/Claude
中的日志文件:
mcp.log
将包含有关 MCP 连接和连接失败的一般日志。- 名为
mcp-server-SERVERNAME.log
的文件将包含来自命名服务端的错误(stderr)日志。
你可以运行以下命令列出最近的日志并跟随任何新的日志:
# 检查Claude的日志以查找错误
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
服务端未在 Claude 中显示
- 检查你的
claude_desktop_config.json
文件语法 - 确保你的项目路径是绝对的而不是相对的
- 完全重新启动 Claude for Desktop
工具调用静默失败
如果 Claude 尝试使用工具但它们失败:
- 检查 Claude 的日志以查找错误
- 验证你的服务端构建和运行没有错误
- 尝试重新启动 Claude for Desktop
这些都不起作用。我该怎么办?
请参阅我们的调试指南以获取更好的调试工具和更详细的指导。
天气 API 问题
错误:无法检索网格点数据
这通常意味着:
- 坐标在美国以外
- NWS API 出现问题
- 你被限速
修复:
- 验证你使用的是美国坐标
- 在请求之间添加小延迟
- 检查 NWS API 状态页面
错误:没有活跃的警报用于 [STATE]
这不是错误 - 这只是意味着该州当前没有天气警报。尝试不同的州或在恶劣天气期间检查。
有关更高级的故障排除,请查看我们的调试 MCP 指南
下一步#
本作品采用《CC 协议》,转载必须注明作者和本文链接