让Claude能力飞升:用MCP协议构建自定义工具实战
引言
Claude 是当下最强大的大语言模型之一,但你有没有遇到过这些场景:需要它读取本地文件、查询实时数据库、调用公司内部 API,或者只是简单地获取当前时间?由于安全和架构限制,Claude 本身无法直接访问外部资源。而 Model Context Protocol (MCP) 正是 Anthropic 推出的标准解决方案——它定义了一套通用协议,让 AI 应用(如 Claude Desktop)能够安全、标准地连接你提供的工具、资源和提示模板。
本文将带你从零开始,掌握 MCP 的核心概念,并通过一个完整可运行的 Python 示例,构建你自己的 Claude 自定义工具。读完你会发现,扩展 Claude 的能力其实比你想象的简单得多。
一、MCP 核心概念:为什么它如此重要?
在 MCP 出现之前,如果你想让大模型集成某个工具,通常需要针对不同模型写不同的插件,或者通过 LangChain 等框架做各种适配。这种碎片化让工具开发者疲于奔命,也让用户难以复用。
MCP 的出现改变了这一切,它像一个“USB-C 接口”:
- 统一标准:无论是 OpenAI、Claude 还是其他模型,只要支持 MCP,就能使用同一个工具服务器。
- 安全隔离:工具运行在独立的进程中,模型只能通过标准协议调用,无法随意执行系统命令。
- 可插拔:你可以在 Claude Desktop 中随时添加或移除 MCP 服务器,无需修改应用本体。
MCP 的核心架构由三个角色构成:
- 主机(Host):即 AI 应用本身,例如 Claude Desktop。
- 客户端(Client):由 Host 内部创建,与指定的 MCP 服务器维持 1:1 连接。
- 服务器(Server):你编写的轻量级程序,负责暴露具体的“能力”,比如工具函数、数据资源、提示模板。
你现在需要的就是开发一个 MCP 服务器,然后将它配置到 Claude Desktop 中。开发一个服务器只需要遵循 MCP 协议,通过标准传输方式(如 stdio)与客户端通信即可。下面,上实战!
二、实战示例:构建一个“系统助手” MCP 服务器
我们将用 Python 编写一个 MCP 服务器,提供三个工具:
- get_current_time:返回当前系统时间。
- add_numbers:计算两个数的和。
- echo:回显输入的字符串(验证工具通信)。
最终效果:在 Claude Desktop 中,可以让 Claude 调用这些工具,比如问它“现在几点”或“帮我算 123+456”。
2.1 环境准备
确保你的 Python 版本 ≥ 3.10,然后安装 MCP 的 Python SDK:
pip install mcp
该库提供了快速构建 MCP 服务器的装饰器和基础类。
2.2 编写服务器代码
新建一个文件 system_assistant.py,内容如下:
#!/usr/bin/env python3
"""
一个简单的 MCP 服务器,暴露三个工具:
- get_current_time: 获取当前时间
- add_numbers: 两数相加
- echo: 回显字符串
"""
import datetime
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationCapabilities
from mcp.server.stdio import stdio_server
import mcp.types as types
# 创建服务器实例
server = Server("system-assistant")
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
"""返回工具列表,Claude 会根据工具描述决定何时调用"""
return [
types.Tool(
name="get_current_time",
description="获取当前系统时间,返回 ISO 格式字符串",
inputSchema={
"type": "object",
"properties": {}, # 无需参数
},
),
types.Tool(
name="add_numbers",
description="将两个数字相加,返回计算结果",
inputSchema={
"type": "object",
"properties": {
"a": {"type": "number", "description": "第一个数"},
"b": {"type": "number", "description": "第二个数"},
},
"required": ["a", "b"],
},
),
types.Tool(
name="echo",
description="回显用户输入的文本,可用于测试",
inputSchema={
"type": "object",
"properties": {
"message": {"type": "string", "description": "要回显的内容"},
},
"required": ["message"],
},
),
]
@server.call_tool()
async def handle_call_tool(
name: str, arguments: dict
) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
"""当 Claude 实际调用工具时,执行对应逻辑"""
if name == "get_current_time":
now = datetime.datetime.now().isoformat()
return [types.TextContent(type="text", text=f"当前时间:{now}")]
elif name == "add_numbers":
a = arguments["a"]
b = arguments["b"]
result = a + b
return [types.TextContent(type="text", text=f"{a} + {b} = {result}")]
elif name == "echo":
msg = arguments["message"]
return [types.TextContent(type="text", text=f"ECHO: {msg}")]
# 未知工具
raise ValueError(f"未知工具: {name}")
async def main():
# 启动基于标准输入输出的 MCP 服务器
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationCapabilities(
sampling={}, # 无需采样能力
experimental={}
),
)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
代码解读:
- @server.list_tools() 注册一个函数,返回可用工具的定义。每个工具包含名称、描述和符合 JSON Schema 的输入参数规范,这能让 Claude 在对话时自动判断何时调用哪个工具。
- @server.call_tool() 是真正的执行逻辑,当 Claude 决定调用某个工具时,MCP 客户端会将工具名称和实参传入该函数,你需要在此完成具体计算,并将结果封装为 TextContent 返回。
- 最后使用 stdio_server() 启动服务器,通过标准输入/输出与 Claude Desktop 通信。这也是的推荐的本地连接方式,简单可靠。
2.3 配置 Claude Desktop
Claude Desktop 支持通过配置文件添加 MCP 服务器。
-
找到配置文件位置:
- macOS:~/Library/Application Support/Claude/claude_desktop_config.json
- Windows:%APPDATA%\Claude\claude_desktop_config.json
- Linux:~/.config/Claude/claude_desktop_config.json -
编辑该文件,添加如下内容(如果文件不存在则新建):
{
"mcpServers": {
"system-assistant": {
"command": "python",
"args": [
"/完整路径/system_assistant.py"
]
}
}
}
将 /完整路径/ 替换为你刚刚保存 system_assistant.py 的绝对路径。
如果你使用虚拟环境,请确保 python 指向虚拟环境中的 Python 解释器,或者使用 uv 等工具管理。
- 重启 Claude Desktop。此时,Claude 会自动连接该 MCP 服务器。
2.4 测试效果
重启后,在 Claude Desktop 的聊天框中检查“可用工具”图标(一个小锤子),你会看到 system-assistant 已经连接。然后可以这样测试:
- 输入:“现在几点了?” → Claude 会调用
get_current_time,回复时间。 - 输入:“帮我算 998 + 254” → 调用
add_numbers,返回计算结果。 - 输入:“请回显 Hello MCP” → 调用
echo,返回ECHO: Hello MCP。
恭喜!你已经成功让 Claude 突破了内置限制,获得了自定义外部能力。
三、常见问题与注意事项
1. 工具描述的重要性
Claude 对工具的调用完全是基于你提供的名称、描述和参数 schema 进行的。如果描述模糊,Claude 可能不会触发调用,或调用时参数传递错误。例如,add_numbers 的描述若写成“计算”,Claude 可能不理解其用途。务必在描述中明确“两个数字相加”、“返回计算结果”等关键词。
2. 传输方式的选择
上述示例使用 stdio 传输,因为大多数本地服务器用这个最简单。MCP 还支持 SSE (Server-Sent Events) 通信,适合远程部署或需要多客户端的场景。但初学者从 stdio 入手即可。
3. 服务器进程管理
当你关闭 Claude Desktop 时,它启动的 MCP 服务器也会终止。但如果你手动杀掉了服务器进程,Claude 的对应能力会变为不可用,需要重启客户端才能恢复。调试期间,直接在终端运行 python system_assistant.py 可以单独测试服务器。
4. 安全考量
- 切勿在工具中执行危险的系统命令或暴露敏感数据,除非你完全清楚风险。
- MCP 协议本身不提供鉴权,若服务器通过 SSE 暴露在网络上,需要自行添加认证层。本地 stdio 模式则相对安全。
- 工具返回的信息会原样展示给用户,注意不要意外泄露密钥等信息。
5. 复杂工具的扩展
当你的工具需要访问数据库、调用 API 时,只需在 handle_call_tool 中完成操作。例如,接入一个天气 API:定义 get_weather 工具,参数为城市名,内部用 httpx 发起请求,将结果格式化返回。MCP 让集成难度大幅降低,你只需专注业务逻辑。
四、总结
本文通过一个极简的 Python MCP 服务器,演示了如何为 Claude Desktop 注入自定义能力。MCP 的价值在于 标准化:你编写的工具不再绑定特定模型,一次开发,多处使用(未来任何支持 MCP 的客户端都能连接)。这种思路极大提升了 AI 应用的扩展性和生态活力。
学习 MCP 不意味着要抛弃现有框架,而是为你的项目增加一种更原生、更通用的集成方式。你可以基于这个示例继续添加更多工具,比如文件操作、知识库查询、甚至控制智能家居。AI 的边界,正由你来定义。
现在,打开你的编辑器,开始构建你的第一个 MCP 工具吧!
延伸阅读:
- MCP 官方文档
- Anthropic 的 Claude 工具使用指南
更多推荐


所有评论(0)