手把手教你用 MCP 协议为 Claude 打造专属工具集,告别重复提问!
引言
你是否曾经让 Claude 帮你查天气、分析文件,或者调用内部 API,却不得不在对话里粘贴整段 JSON,甚至手动解释返回结果?随着大语言模型的能力越来越强,我们不再满足于文本对话,更希望 AI 能像真实的工作助手一样,直接使用我们指定的工具对外交互。过去这种集成往往需要搭建复杂的中间服务,如今有了 Model Context Protocol(MCP),一切都变得简单而优雅。
本文将带你从零开始,理解 MCP 的核心理念,并通过一个完整的天气查询工具实战,为 Claude 客户端(如 Claude Desktop)构建专属的工具服务器。你会看到,仅仅几十行 Python 代码,就能让 Claude 在回答中实时拉取外部数据,甚至执行你定义好的任何操作。读完此文,你将能够:
- 理解 MCP 的设计思想与核心概念
- 使用 Python 快速构建一个 MCP Server
- 注册自定义工具并配置 Claude Desktop 使用
- 掌握调试、安全与常见避坑要点
让我们直接开始吧。
核心概念:MCP 是什么?
MCP(Model Context Protocol)是由 Anthropic 推出的一种开放协议,它标准化了 AI 模型与外部工具、数据源之间的交互方式。你可以把它想象成 AI 世界的“USB‑C 接口”——只要遵循 MCP 规范,任何客户端(Claude Desktop、IDE 插件、自研应用)都能无缝连接任何服务器,发现并使用其提供的 工具(Tools)、资源(Resources) 和 提示(Prompts)。
MCP 架构一览
MCP 采用客户端‑服务器(Client‑Server)架构,通信基于 JSON‑RPC 2.0,底层传输可以是标准输入输出(stdio)或 HTTP+SSE。一次典型的交互流程如下:
- Server 启动 并暴露自己的能力(例如一个
get_weather工具)。 - Client(如 Claude Desktop) 与 Server 建立连接,进行能力协商。
- 用户在对话中提出请求,Claude 判断需要使用某个工具。
- Client 向 Server 发送
tools/call请求,携带工具名和参数。 - Server 执行逻辑(调用 API、查询数据库、运行脚本等),并将结果返回。
- Claude 将结果自然整合到回答中,呈现给用户。
整个过程对用户透明,仿佛 Claude 天生就拥有这些能力。
三个核心元素
- 工具(Tools):模型可以调用的函数。每个工具包含名称、描述、输入参数的 JSON Schema。
- 资源(Resources):模型可以直接读取的数据,如文件内容、数据库记录。
- 提示(Prompts):预定义的交互模板,帮助用户快速发起特定类型的请求。
本文我们聚焦在最常用、最灵活的 自定义工具 上,构建一个 MCP Server,为 Claude 提供实时天气查询能力。
实战:构建一个天气查询 MCP 工具
我们将创建一个 Python MCP Server,注册 get_weather 工具,它会调用免费的 wttr.in API 获取指定城市的当前天气,并返回格式化后的文本。随后我们配置 Claude Desktop 连接此 Server,在对话中直接询问天气。
环境准备
本示例基于 Python 3.10+ 和官方 MCP Python SDK。首先安装依赖:
pip install "mcp[cli]" httpx
mcp[cli]:包含 MCP Server/Client 的基础库及命令行调试工具。httpx:异步 HTTP 客户端,用于请求天气 API。
编写 MCP Server 代码
新建文件 weather_server.py,内容如下:
import json
import httpx
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationCapabilities
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
# 创建 MCP Server 实例
server = Server("weather-server")
# 定义工具的具体实现
async def handle_get_weather(city: str) -> str:
"""
实际调用 wttr.in API,获取指定城市的天气信息。
返回简洁的文本描述,便于 Claude 理解。
"""
# wttr.in 提供多种格式,这里使用 JSON 格式避免解析 HTML
url = f"https://wttr.in/{city}?format=j1"
async with httpx.AsyncClient() as client:
resp = await client.get(url)
resp.raise_for_status()
data = resp.json()
# 提取当前天气数据
current = data["current_condition"][0]
weather_desc = current["weatherDesc"][0]["value"]
temp_c = current["temp_C"]
humidity = current["humidity"]
feels_like = current["FeelsLikeC"]
return (
f"{city} 当前天气:{weather_desc}\n"
f"气温:{temp_c}°C(体感 {feels_like}°C)\n"
f"湿度:{humidity}%"
)
# 注册工具:定义名称、描述、参数 schema
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="get_weather",
description="查询指定城市的实时天气信息,包括天气状况、气温、湿度等。",
inputSchema={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,例如 Beijing, London, Tokyo"
}
},
"required": ["city"]
}
)
]
# 处理工具调用请求
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "get_weather":
city = arguments.get("city", "")
if not city:
raise ValueError("city 参数不能为空")
result_text = await handle_get_weather(city)
return [TextContent(type="text", text=result_text)]
else:
raise ValueError(f"未知工具: {name}")
# 主函数:启动 stdio 传输的 Server
async def main():
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationCapabilities(
sampling={}, # 不需要采样能力
experimental={},
),
notification_options=NotificationOptions(),
)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
这段代码清晰地体现了 MCP Server 的三个关键部分:
- 工具清单 (
list_tools):向客户端声明服务器提供了哪些工具,以及每个工具的参数格式(JSON Schema)。Claude 会根据这里的描述,在对话中准确理解工具的用途和调用方式。 - 工具执行 (
call_tool):当客户端请求调用某个工具时,该函数被触发,负责解析参数、执行实际业务逻辑(此处为 HTTP 请求),并返回TextContent类型的结果。 - 传输层:我们使用
stdio即标准输入输出,这是 MCP 本地使用最方便的方式,无需开放网络端口。
本地测试工具
在正式接入 Claude 前,我们可以用 mcp dev 命令快速测试工具是否正常工作:
mcp dev weather_server.py
这会启动一个交互式测试环境,你可以模拟客户端调用:
>> tools/call get_weather {"city":"Beijing"}
如果一切正常,你会看到类似输出:
Beijing 当前天气:Sunny
气温:22°C(体感 21°C)
湿度:35%
配置 Claude Desktop 使用自定义工具
假设你已安装 Claude Desktop。我们需要编辑其配置文件,告诉它启动我们刚刚编写的 MCP Server。
-
找到配置文件:
- macOS:~/Library/Application Support/Claude/claude_desktop_config.json
- Windows:%APPDATA%\Claude\claude_desktop_config.json
如果文件不存在,可以手动创建。 -
添加 MCP Server 配置:
{
"mcpServers": {
"weather-server": {
"command": "python",
"args": ["/absolute/path/to/weather_server.py"],
"env": {}
}
}
}
请将路径替换为你的
weather_server.py的绝对路径。如果你使用的是虚拟环境,记得将command设为虚拟环境中的 python 解释器路径。
- 重启 Claude Desktop:完全退出后重新打开,Claude 会自动连接配置的 MCP Server。
验证连接:点击输入框旁的工具图标(🔧),你应该能看到 weather-server 及其下的 get_weather 工具,说明集成成功。
在对话中使用天气工具
现在你可以直接向 Claude 提问:
北京今天天气怎么样?
Claude 会判断需要调用 get_weather 工具,自动发送城市名“Beijing”,获取结果后组织回答:
北京当前天气:晴,气温 22°C(体感 21°C),湿度 35%。今天天气不错,适合户外活动哦!
整个过程完全在对话中完成,你再也不需要手动查询天气并粘贴结果了。
增强实战:集成更多工具
了解了基础流程后,你可以轻松扩展服务器,添加更多工具。例如,我们再加一个简单的“日期计算”工具,帮助 Claude 回答“100天后是几号”这类问题。只需在 list_tools 和 call_tool 中添加新条目:
# 在 list_tools 中追加
Tool(
name="add_days_to_today",
description="计算从今天起若干天后的日期(返回 YYYY-MM-DD 格式)。",
inputSchema={
"type": "object",
"properties": {
"days": {"type": "integer", "description": "增加的天数"}
},
"required": ["days"]
}
)
# 在 call_tool 中添加处理分支
from datetime import date, timedelta
elif name == "add_days_to_today":
days = int(arguments["days"])
future = date.today() + timedelta(days=days)
result_text = future.isoformat()
return [TextContent(type="text", text=result_text)]
更新服务配置,重启 Claude Desktop 后,它就能同时使用天气和日期计算工具,组合完成任务。
常见问题与注意事项
1. 安全性:谁可以调用我的工具?
MCP 工具运行在本地,使用 stdio 传输时只有本机进程可以访问,相对安全。但如果 Server 通过 HTTP 暴露,务必加上鉴权(目前社区方案使用 OAuth 或 API Key)。切勿在工具中直接执行未经校验的用户输入,避免命令注入。对于敏感操作(如数据库写入),建议在工具内部做二次确认或限制。
2. 调试工具无响应?
- 确认
weather_server.py能独立运行,没有 import 错误。 - 使用
mcp dev weather_server.py单独测试,查看错误堆栈。 - 检查配置文件路径、python 命令是否正确。在终端中手动执行命令确认可以启动。
- Claude Desktop 的日志位于
~/Library/Logs/Claude/(macOS),可作为排查线索。
3. 工具返回的内容 Claude 不识别
MCP 工具应返回清晰的文本描述,或者符合 TextContent 的结构。如果返回的是复杂 JSON,Claude 也可能处理,但最好在工具描述中说明返回格式。另外,避免过长的文本,必要时截断或分页。
4. 异步与性能
本示例使用了 httpx.AsyncClient 和异步 Server,这是推荐的模式。如果你的工具涉及 I/O 密集操作,务必使用异步库,防止阻塞整个 Server。对于 CPU 密集型任务,可考虑放入线程池执行。
5. 工具过多时的命名冲突
不同 MCP Server 可以注册同名工具吗?可以,但用户在 Claude Desktop 中会看到两个来源的工具,选择时容易混淆。建议为功能明确的 Server 起一个独立的名称,工具名保持简洁且语义唯一。
总结
通过本文,你不仅理解了 MCP 的设计理念,还亲手打造了一个实时天气查询工具,并成功将其接入 Claude Desktop。整个流程无需复杂的前端、鉴权,只需几十行 Python 代码,就让大模型与真实世界的数据流动了起来。
MCP 的出现极大地降低了 AI 集成的门槛,未来我们可以预见会有越来越多的工具服务器涌现,形成繁荣的生态。无论你是想连接企业内部 API、自动化日常任务,还是搭建个人知识库,MCP + Claude 的组合都提供了一个强大且灵活的解决方案。
现在就动手,把你重复性的提问变成工具,让 Claude 成为你真正的智能助手吧!
扩展阅读与资源
- MCP 官方文档
- MCP Python SDK
- wttr.in 天气 API 文档
更多推荐
所有评论(0)