引言
你是否曾经让 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]" httpxmcp[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 文档