第 4 课:自定义工具——MCP Server
为什么需要自定义工具?
SDK 自带的工具(Bash、Read、Write 等)能做很多事,但有时候你需要更专业的工具:
内置工具能做的:
✅ 执行 shell 命令
✅ 读写文件
你需要的:
❌ 调用公司内部 API
❌ 查询数据库
❌ 操作 Docker 容器
❌ 读取 Kubernetes Pod 状态
❌ 发送告警通知
MCP(Model Context Protocol)Server 就是用来解决这个问题的——把任何 Python 函数变成 AI 可以调用的工具。
@tool 装饰器
最核心的就是 @tool 装饰器。它把一个普通的 Python 函数变成 AI 的工具:
from claude_agent_sdk import tool
@tool("工具名", "工具描述", {"参数名": 参数类型})
async def 你的函数(args):
# 你的逻辑
return {"content": [{"type": "text", "text": "返回结果"}]}
实战:创建 Git 工具
from claude_agent_sdk import tool
import subprocess
@tool("git_status", "查看 Git 仓库状态", {})
async def git_status(args):
"""查看当前仓库的 git status"""
result = subprocess.run(
["git", "status", "--porcelain"],
capture_output=True, text=True
)
output = result.stdout if result.stdout else "工作区是干净的"
return {"content": [{"type": "text", "text": output}]}
@tool("git_log", "查看最近的提交记录", {"count": int})
async def git_log(args):
"""查看最近 N 条提交记录"""
count = args.get("count", 5)
result = subprocess.run(
["git", "log", f"--oneline", f"-{count}"],
capture_output=True, text=True
)
return {"content": [{"type": "text", "text": result.stdout}]}
@tool("git_diff", "查看文件改动", {"file": str})
async def git_diff(args):
"""查看指定文件的 diff"""
file_path = args.get("file", "")
cmd = ["git", "diff", file_path] if file_path else ["git", "diff"]
result = subprocess.run(cmd, capture_output=True, text=True)
return {"content": [{"type": "text", "text": result.stdout or "没有改动"}]}
注册到 MCP Server
写好工具函数后,用 create_sdk_mcp_server() 把它们打包成一个服务器:
from claude_agent_sdk import create_sdk_mcp_server
# 把工具打包成一个 MCP 服务器
git_server = create_sdk_mcp_server(
name="git-tools",
version="1.0.0",
tools=[git_status, git_log, git_diff],
)
在 query() 或 Client 中使用
from claude_agent_sdk import query, ClaudeAgentOptions
options = ClaudeAgentOptions(
mcp_servers={"git": git_server}, # 注册 MCP 服务器
allowed_tools=[
"mcp__git__git_status", # 格式:mcp__服务器名__工具名
"mcp__git__git_log",
"mcp__git__git_diff",
],
system_prompt="你是 Git 助手,帮用户管理代码仓库。",
)
async for msg in query(
prompt="看看仓库状态,最近 3 条提交,以及有什么改动",
options=options,
):
# 处理消息...
pass
AI 现在可以像调用内置工具一样调用你的自定义工具了!
工具命名规则
自定义工具在 allowed_tools 里的名字格式是:
mcp__<服务器名>__<工具名>
例子:
mcp__git__git_status
mcp__git__git_log
mcp__docker__list_containers
更多 DevOps 工具示例
Docker 工具
@tool("list_containers", "列出 Docker 容器", {"all": bool})
async def list_containers(args):
show_all = args.get("all", False)
cmd = ["docker", "ps"]
if show_all:
cmd.append("-a")
result = subprocess.run(cmd, capture_output=True, text=True)
return {"content": [{"type": "text", "text": result.stdout}]}
@tool("container_logs", "查看容器日志", {"container": str, "lines": int})
async def container_logs(args):
container = args["container"]
lines = args.get("lines", 50)
result = subprocess.run(
["docker", "logs", "--tail", str(lines), container],
capture_output=True, text=True
)
output = result.stdout + result.stderr
return {"content": [{"type": "text", "text": output}]}
健康检查工具
import urllib.request
import json
@tool("health_check", "检查服务健康状态", {"url": str})
async def health_check(args):
url = args["url"]
try:
req = urllib.request.urlopen(url, timeout=5)
status = req.getcode()
return {"content": [{"type": "text",
"text": f"✅ {url} → HTTP {status}"}]}
except Exception as e:
return {"content": [{"type": "text",
"text": f"❌ {url} → 失败: {str(e)}"}],
"is_error": True}
告警通知工具
@tool("send_alert", "发送告警通知", {"message": str, "level": str})
async def send_alert(args):
message = args["message"]
level = args.get("level", "info")
# 这里可以接入你的告警系统:飞书、钉钉、Slack 等
print(f"[{level.upper()}] 告警: {message}")
return {"content": [{"type": "text",
"text": f"告警已发送: [{level}] {message}"}]}
工具中访问应用状态
MCP 工具的一个强大之处:工具函数可以直接访问你的 Python 应用状态。
# 应用级别的状态
deployment_history = []
@tool("record_deployment", "记录部署", {"version": str, "env": str})
async def record_deployment(args):
# 直接访问应用状态!
deployment_history.append({
"version": args["version"],
"env": args["env"],
"time": datetime.now().isoformat(),
})
return {"content": [{"type": "text",
"text": f"已记录部署: {args['version']} → {args['env']}"}]}
@tool("list_deployments", "查看部署历史", {})
async def list_deployments(args):
if not deployment_history:
return {"content": [{"type": "text", "text": "没有部署记录"}]}
history = "\n".join(
f" {d['version']} → {d['env']} @ {d['time']}"
for d in deployment_history
)
return {"content": [{"type": "text", "text": history}]}
这比外部 MCP 服务器方便得多——不用 HTTP 通信、不用序列化,直接共享 Python 内存。
本课小结
@tool装饰器把 Python 函数变成 AI 的工具create_sdk_mcp_server()把工具打包成 MCP 服务器- 工具命名格式:
mcp__<服务器名>__<工具名> - 工具函数可以直接访问应用状态
- 可以包装任何 API:Git、Docker、数据库、告警系统
课后练习
- 把上面的 Git 工具跑起来,让 AI 帮你查看仓库状态
- 写一个
disk_usage工具,让 AI 能查看磁盘使用情况 - 把多个工具合到一个 MCP Server 里,让 AI 同时使用