通过 SDK 内置的进程内 MCP 服务器定义自定义工具,让 Claude 可以调用你的函数、访问数据库、调用外部 API 或执行领域特定操作。无需启动独立进程。
核心机制
工具定义四要素:
- name:唯一标识符,Claude 用它调用工具
- description:工具功能描述,Claude 据此决定何时调用
- input schema:Python 用 dict 或 JSON Schema,TypeScript 用 Zod schema
- handler:异步处理函数,接收验证后的参数,返回结果对象
工具命名格式:注册到 MCP 服务器后,工具名变为 mcp__<server_name>__<tool_name>。
handler 返回值结构:
{
"content": [{"type": "text", "text": "结果文本"}], # 必须
"is_error": True, # 可选,标记工具失败(Agent 循环继续)
"structuredContent": {...} # 可选,机器可读的结构化数据(Python 不支持)
}错误处理原则:handler 抛出未捕获异常会终止整个 Agent 循环;返回 is_error: True 则 Claude 看到错误信息并可调整策略,循环继续。
关键细节
from claude_agent_sdk import tool, create_sdk_mcp_server, query, ClaudeAgentOptions
@tool(
"get_temperature",
"Get the current temperature at a location",
{"latitude": float, "longitude": float},
)
async def get_temperature(args):
# 调用外部 API...
return {"content": [{"type": "text", "text": f"Temperature: 72°F"}]}
weather_server = create_sdk_mcp_server(
name="weather",
version="1.0.0",
tools=[get_temperature],
)
async for message in query(
prompt="What's the temperature in San Francisco?",
options=ClaudeAgentOptions(
mcp_servers={"weather": weather_server},
allowed_tools=["mcp__weather__get_temperature"],
),
):
...工具注解(Annotations):
readOnlyHint: True- 无副作用,允许并发执行destructiveHint: True- 可能有破坏性操作(仅信息性)idempotentHint: True- 重复调用无额外效果(仅信息性)
返回图片:content 中使用 type: "image",data 字段为 base64 编码(不含 data URI 前缀)。
工具可用性控制:
tools: ["Read", "Grep"]- 只让 Claude 看到这些内置工具(从上下文移除其他)allowed_tools- 预批准工具(工具仍在上下文中,只是无需审批)disallowed_tools- 阻止工具调用(工具仍在上下文中,Claude 可能尝试后被拒绝)
与其他概念的关联
- mcp - 连接外部 MCP 服务器(vs 进程内自定义工具)
- tool-search - 工具数量多时按需加载
- permissions - 工具权限控制
实践要点
- 工具数量多时(>10 个),考虑使用 tool-search 按需加载,避免占满上下文
- Python 的 dict schema 不支持 enum,需要 enum 约束时使用完整 JSON Schema dict
- 可选参数:TypeScript 用
.default(),Python 在 schema 中省略该字段并在 handler 中用args.get()读取 - 通配符
mcp__weather__*可一次预批准服务器的所有工具