写在前面:还是有不少读者私信我关于如何编写一个MCP工具,虽然MCP是24年出来的产物,但也不妨在25年温故而知新
直到我了解了MCP(Model Context Protocol)——一个能让AI"长出手脚"的协议。今天就来聊聊这个能让AI真正"干活"的神器。
一、先说说AI的"残疾"问题
在聊MCP之前,我们先来看看传统AI有多"残疾":
是的,全都做不到。
AI的本质局限
传统的AI模型(比如GPT、Claude)本质上是什么?是一个超级文本处理器。
它能做的事情:
- ✅ 理解你说的话
- ✅ 根据训练知识回答问题
- ✅ 生成文本、代码、文章
- ✅ 分析和总结内容
它做不到的事情:
- ❌ 知道现在几点
- ❌ 读取你电脑上的文件
- ❌ 帮你发送邮件
- ❌ 查询实时股票价格
- ❌ 操作任何外部系统
打个比方:传统AI就像一个被关在玻璃房里的天才——脑子很好使,但没有手脚,出不去,摸不到外面的世界。
💡 为什么会这样?
因为AI模型在训练完成后,就被"定格"了。它的知识来自训练数据,训练数据是什么时候截止的,它的知识就到什么时候。
而且,出于安全考虑,AI默认是不能直接访问外部系统的——毕竟谁也不想AI随便读取你的隐私文件或者乱发邮件对吧?
但问题是,这也让AI变得"不接地气"。很多实际工作,光靠"说"是完成不了的。
二、MCP是什么?给AI装"手脚"的协议
**MCP(Model Context Protocol,模型上下文协议)**是Anthropic公司在2024年11月发布的一个开放标准。
用一句话解释:
MCP就像是AI的"USB接口"——让AI可以插上各种"外设",获得新的能力。
🔌 MCP的核心思想
MCP定义了一套标准的"对话语言",让AI和外部工具可以互相"听懂"。
| 角色 | 作用 | 类比 |
|---|---|---|
| MCP Server | 提供具体能力的"工具箱" | USB设备(键盘、鼠标等) |
| MCP Client | 负责沟通的"中间人" | USB接口 |
| AI Model | 决定什么时候用什么工具 | 电脑主机 |
有了MCP,AI的能力就从"只能说"变成了"能说也能做":
三、举个栗子:让AI知道"现在几点"
光说理论太抽象,我们来做一个最简单的例子——让AI能够回答"现在几点了"。
整体流程
🛠️ 动手实现
好,我们来一步步实现这个功能。
第一步:准备环境
首先确保你有Python环境(推荐3.10以上版本)。
# 创建项目目录
mkdir my-first-mcp
cd my-first-mcp
# 创建虚拟环境(推荐)
python -m venv venv
source venv/bin/activate # Mac/Linux
# 或者 venv\Scripts\activate # Windows
第二步:安装依赖
pip install mcp
第三步:编写MCP Server
创建一个文件 time_server.py:
"""
一个简单的MCP Server示例:获取当前时间
"""
from datetime import datetime
from zoneinfo import ZoneInfo
from mcp.server.fastmcp import FastMCP
# 创建MCP服务器实例
mcp = FastMCP("时间助手")
@mcp.tool()
def get_current_time(timezone: str = "Asia/Shanghai") -> str:
"""
获取指定时区的当前时间
Args:
timezone: 时区名称,默认为中国时区(Asia/Shanghai)
Returns:
格式化的当前时间字符串
"""
try:
tz = ZoneInfo(timezone)
now = datetime.now(tz)
# 返回友好的时间格式
return now.strftime("%Y年%m月%d日 %H:%M:%S")
except Exception as e:
return f"获取时间失败:{str(e)}"
@mcp.tool()
def get_weekday() -> str:
"""
获取今天是星期几
Returns:
星期几的中文表示
"""
weekdays = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
today = datetime.now(ZoneInfo("Asia/Shanghai"))
return weekdays[today.weekday()]
@mcp.tool()
def time_until(target_time: str) -> str:
"""
计算距离目标时间还有多久
Args:
target_time: 目标时间,格式为 HH:MM
Returns:
距离目标时间的描述
"""
try:
now = datetime.now(ZoneInfo("Asia/Shanghai"))
target = datetime.strptime(target_time, "%H:%M").replace(
year=now.year, month=now.month, day=now.day,
tzinfo=ZoneInfo("Asia/Shanghai")
)
# 如果目标时间已过,算到明天
if target < now:
target = target.replace(day=now.day + 1)
diff = target - now
hours, remainder = divmod(int(diff.total_seconds()), 3600)
minutes, _ = divmod(remainder, 60)
return f"距离 {target_time} 还有 {hours}小时{minutes}分钟"
except Exception as e:
return f"计算失败:{str(e)}"
if __name__ == "__main__":
mcp.run()
第四步:运行测试
python time_server.py
如果没有报错,说明MCP Server已经启动成功了!
第五步:配置Claude Desktop(可选)
如果你使用Claude Desktop,可以在配置文件中添加这个MCP Server。
找到配置文件位置:
- Mac:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
添加以下配置:
{
"mcpServers": {
"time-server": {
"command": "python",
"args": ["/你的路径/time_server.py"]
}
}
}
重启Claude Desktop后,你就可以问它"现在几点"了,它会真的告诉你准确时间!
四、MCP工具的工作原理详解
上面我们跑通了一个例子,现在来深入理解一下MCP是怎么工作的。
完整通信流程
sequenceDiagram
participant U as 用户
participant C as Claude
participant MC as MCP Client
participant MS as MCP Server
U->>C: 现在几点了?
C->>C: 分析:需要获取实时时间
C->>MC: 请求调用 get_current_time
MC->>MS: 发送工具调用请求
MS->>MS: 执行 Python 代码获取系统时间
MS->>MC: 返回:2025年12月30日 15:25:30
MC->>C: 返回时间数据
C->>C: 组织自然语言回复
C->>U: 现在是2025年12月30日下午3点25分30秒
MCP工具的三要素
每个MCP工具都需要定义三个东西:
| 要素 | 作用 | 在代码中的体现 |
|---|---|---|
| 名称 | 工具的唯一标识 | 函数名,如 get_current_time |
| 描述 | 告诉AI这个工具能干嘛 | docstring,AI根据描述决定是否调用 |
| 参数 | 工具需要的输入 | 函数参数,如 timezone: str |
@mcp.tool()
def get_current_time(timezone: str = "Asia/Shanghai") -> str:
"""
获取指定时区的当前时间 ← 这是描述,AI会读这个
Args:
timezone: 时区名称 ← 这是参数说明
"""
# 实际执行的代码
...
🧠 AI是怎么决定用哪个工具的?
这是很多人好奇的问题。答案是:AI根据工具的描述来判断。
当你问"现在几点"时,AI会:
- 看到
get_current_time工具的描述是"获取指定时区的当前时间" - 判断这个工具能回答你的问题
- 决定调用这个工具
所以,写好工具描述非常重要!描述写得好,AI才能在正确的时候调用正确的工具。
五、更多实用MCP工具示例
光有时间工具还不够,再给大家展示几个实用的MCP工具思路:
示例一:文件读取工具 📁
@mcp.tool()
def read_file(file_path: str) -> str:
"""
读取指定路径的文本文件内容
Args:
file_path: 文件的完整路径
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return f"文件不存在:{file_path}"
except Exception as e:
return f"读取失败:{str(e)}"
示例二:天气查询工具 🌤️
import requests
@mcp.tool()
def get_weather(city: str) -> str:
"""
查询指定城市的当前天气
Args:
city: 城市名称,如"北京"、"上海"
"""
# 这里用免费的天气API
api_url = f"https://wttr.in/{city}?format=3"
try:
response = requests.get(api_url, timeout=10)
return response.text
except Exception as e:
return f"查询天气失败:{str(e)}"
示例三:计算器工具
@mcp.tool()
def calculate(expression: str) -> str:
"""
计算数学表达式的结果
Args:
expression: 数学表达式,如 "2 + 3 * 4"
"""
try:
# 安全地计算表达式
result = eval(expression, {"__builtins__": {}}, {})
return f"{expression} = {result}"
except Exception as e:
return f"计算失败:{str(e)}"
示例四:翻译工具
@mcp.tool()
def translate_to_english(text: str) -> str:
"""
将中文翻译成英文
Args:
text: 要翻译的中文文本
"""
# 这里可以接入翻译API
# 示例使用免费的API
...
六、MCP工具开发最佳实践
用了MCP一段时间,总结了一些开发技巧:
技巧一:工具描述要写清楚
# ❌ 不好的写法
@mcp.tool()
def do_something(x):
"""处理数据""" # 太模糊,AI不知道什么时候用
...
# ✅ 好的写法
@mcp.tool()
def calculate_monthly_salary(base_salary: float, bonus: float) -> str:
"""
计算月薪总额(基本工资+奖金)
当用户询问薪资计算、月薪总额、工资加奖金等问题时使用此工具
Args:
base_salary: 基本工资,单位为元
bonus: 奖金,单位为元
Returns:
月薪总额的详细说明
"""
...
技巧二:做好错误处理
@mcp.tool()
def read_file(file_path: str) -> str:
"""读取文件内容"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return f"❌ 文件不存在:{file_path}"
except PermissionError:
return f"❌ 没有权限读取:{file_path}"
except Exception as e:
return f"❌ 读取出错:{str(e)}"
技巧三:返回结构化信息
# ❌ 不好的返回
return "15:25"
# ✅ 好的返回
return f"当前时间:2025年12月30日 15:25:30(北京时间)"
技巧四:合理拆分工具
| 方式 | 优点 | 缺点 |
|---|---|---|
| 一个大工具 | 简单 | AI难以准确调用 |
| 多个小工具 | AI容易选择正确的 | 代码稍多 |
七、MCP vs 传统方案对比
可能有人会问:用API不也能实现这些功能吗?
确实可以,但MCP有独特的优势:
详细对比
| 维度 | 传统API调用 | MCP协议 |
|---|---|---|
| AI集成 | 需要自己写调用逻辑 | AI自动判断和调用 |
| 标准化 | 每个API格式不同 | 统一的协议标准 |
| 发现机制 | 需要预先知道有哪些API | AI自动发现可用工具 |
| 权限控制 | 各自实现 | 协议层面支持 |
| 错误处理 | 需要自己处理 | 标准化的错误格式 |
总结:MCP不是要替代API,而是在AI和API之间建立一个标准化的"翻译层",让AI能更聪明地使用各种工具。
八、MCP生态:现成的工具推荐
如果你不想自己开发,社区已经有很多现成的MCP工具可以直接用:
| 工具名称 | 功能 | 适用场景 |
|---|---|---|
| filesystem | 文件系统操作 | 读写文件、创建目录 |
| github | GitHub操作 | 创建Issue、PR、查看代码 |
| postgres | 数据库操作 | 查询和操作PostgreSQL |
| brave-search | 网络搜索 | 实时搜索互联网信息 |
| puppeteer | 浏览器自动化 | 网页截图、自动化测试 |
| slack | Slack消息 | 发送消息、管理频道 |
这些工具都可以在 MCP官方仓库 找到。
九、常见问题解答
❓ Q1:MCP安全吗?会不会泄露我的数据?
答:MCP本身只是一个协议,安全性取决于你如何实现。建议:
- 只授权必要的权限
- 敏感操作加确认机制
- 本地运行的工具只在本地工作
❓ Q2:MCP支持哪些AI模型?
答:目前主要支持Claude。不过因为是开放协议,其他模型也在逐步支持中。
❓ Q3:不会写代码能用MCP吗?
答:可以用社区现成的工具。配置一下就能用,不需要自己写代码。
❓ Q4:MCP和Function Calling有什么区别?
答:Function Calling是各家AI自己的实现,格式不统一。MCP是开放标准,更通用。
十、最后说几句
MCP的出现,让AI从"只会说"变成了"能说能做"。这是一个重要的进化。
我们正处在AI 3.0的早期阶段。MCP就是这个阶段的关键技术之一。
从一个简单的"获取当前时间"开始,你可以给AI装上越来越多的"手脚"——读文件、查数据库、发邮件、控制智能家居...
AI不再是玻璃房里的天才,而是真正能帮你干活的助手。
这才是AI应该有的样子。
相关资源:
- MCP官方文档:modelcontextprotocol.io
- MCP工具仓库:github.com/modelcontex…
- Anthropic官方博客
彩蛋:
其实"让AI调用工具"这个想法并不新鲜。早在ChatGPT的插件系统就在尝试了。但那个系统比较封闭,而且后来还被砍了。
MCP的聪明之处在于:它是一个开放标准。任何人都可以基于这个标准开发工具,任何AI都可以接入这个协议。
开放带来繁荣。期待看到MCP生态越来越丰富的那一天。
如果这篇文章对你有帮助,欢迎分享给需要的朋友~